def calc_min_smearing(self, verbose=False): """Calculate minimum (optimal) smearing. Inputs: verbose: Print information to screen (Default = False) """ half_dDMmin = 0.5 * ALLOW_DMSTEPS[0] self.min_chan_smear = psr_utils.dm_smear(self.loDM + half_dDMmin, self.obs.chanwidth, self.obs.fctr) self.min_bw_smear = psr_utils.dm_smear(half_dDMmin, self.obs.BW, self.obs.fctr) self.min_total_smear = np.sqrt(2 * self.obs.dt ** 2.0 + self.min_chan_smear ** 2.0 + self.min_bw_smear ** 2.0) self.best_resolution = max([self.req_resolution, self.min_chan_smear, self.min_bw_smear, self.obs.dt]) self.resolution = self.best_resolution if verbose: print print "Minimum total smearing : %.3g s" % self.min_total_smear print "--------------------------------------------" print "Minimum channel smearing : %.3g s" % self.min_chan_smear print "Minimum smearing across BW : %.3g s" % self.min_bw_smear print "Minimum sample time : %.3g s" % self.obs.dt print print "Setting the new 'best' resolution to : %.3g s" % self.best_resolution # See if the data is too high time resolution for our needs if (FF * self.min_chan_smear > self.obs.dt) or (self.resolution > self.obs.dt): if self.resolution > FF * self.min_chan_smear: if verbose: print " Note: resolution > dt (i.e. data is higher resolution than needed)" self.resolution = self.resolution else: if verbose: print " Note: min chan smearing > dt (i.e. data is higher resolution than needed)" self.resolution = FF * self.min_chan_smear
def _compute_rating(self, cand): """Return a rating for the candidate. The rating value is the ratio of the width of the narrowest gaussian component to the DM smearing. Input: cand: A Candidate object to rate. Output: value: The rating value. """ pfd = cand.get_from_cache('pfd') mgauss = cand.get_from_cache('multigaussfit') ncomp = len(mgauss.components) if not ncomp: raise utils.RatingError("Bad number of components for single " \ "gaussian fit (%d)" % ncomp) # Get the period period = pfd.bary_p1 or pfd.topo_p1 if period is None: raise utils.RatingError("Bad period in PFD file (%f)" % period) f_ctr = (pfd.hifreq + pfd.lofreq)/2.0 dm_smear = psr_utils.dm_smear(pfd.bestdm, pfd.chan_wid, f_ctr) width_phs = np.sqrt(dm_smear**2 + pfd.dt**2)/period minfwhm = min([comp.fwhm for comp in mgauss.components]) return width_phs/minfwhm
def _compute_rating(self, cand): """Return a rating for the candidate. The rating value is the ratio of the width of the narrowest gaussian component to the DM smearing. Input: cand: A Candidate object to rate. Output: value: The rating value. """ pfd = cand.pfd mgauss = cand.multigaussfit ncomp = len(mgauss.components) if not ncomp: raise utils.RatingError("Bad number of components for single " \ "gaussian fit (%d)" % ncomp) # Get the period period = pfd.bary_p1 or pfd.topo_p1 if period is None: raise utils.RatingError("Bad period in PFD file (%f)" % period) f_ctr = (pfd.hifreq + pfd.lofreq) / 2.0 dm_smear = psr_utils.dm_smear(pfd.bestdm, pfd.chan_wid, f_ctr) width_phs = np.sqrt(dm_smear**2 + pfd.dt**2) / period minfwhm = min([comp.fwhm for comp in mgauss.components]) return width_phs / minfwhm
def subband_smear(DM, subDM, subBW, fctr): """ subband_smear(DM, subDM, subBW, fctr): Return the smearing in ms caused by subbanding at DM='DM' given subbands of bandwidth 'subBW' (MHz) at DM='subDM'. All values are computed at the frequency fctr in MHz. """ return 1000.0 * pu.dm_smear(num.fabs(DM-subDM), subBW, fctr)
def fit_powers(self, freqlim=None, use_errors=True, **kwargs): # Use iminuit to fit power-law + DC to powers import iminuit if freqlim is None: freqlim = np.inf if self.inf.DM > 0: tdm = psr_utils.dm_smear(self.inf.DM, self.inf.BW, self.inf.lofreq + 0.5 * self.inf.BW) freqlim = 1.0 / tdm print "Dispersion smearing time: %.2f ms" % (1000.0 * tdm) freqlim = min(10.0, freqlim) print "Only fitting using frequencies up to %.2f Hz" % freqlim iuse = (self.freqs < freqlim) iuse[0] = 0 # Always ignore zeroth element if use_errors: # Compute power errors self.estimate_power_errors() # Define function to minimize def to_minimize(amp, index, dc): model = power_law(self.freqs[iuse], amp, index, dc) diff = model - self.powers[iuse] #plt.figure() #plt.plot(self.freqs[1:], self.powers[1:], 'r-', alpha=0.5) #plt.plot(self.freqs[iuse], self.powers[iuse], 'k-', alpha=0.5) #plt.plot(self.freqs[iuse], model, 'k--', lw=2) #plt.xscale('log') #plt.yscale('log') #plt.xlabel("Freq (Hz)") #plt.ylabel("Raw Power") #plt.show() if use_errors: diff /= self.errs[iuse] return np.sum(diff**2) white = self.estimate_white_power_level(1000) kwargs.setdefault('amp', 1e14) kwargs.setdefault('error_amp', 1e12) kwargs.setdefault('limit_amp', (0, 1e20)) kwargs.setdefault('index', -1.5) kwargs.setdefault('error_index', .1) kwargs.setdefault('limit_index', (-10.0, 0.0)) kwargs.setdefault('dc', white) kwargs.setdefault('error_dc', white * 0.1) #kwargs.setdefault('limit_dc', (white*0.01, np.max(self.powers[1:]))) kwargs.setdefault('fix_dc', True) m = iminuit.Minuit(to_minimize, frontend=iminuit.ConsoleFrontend, print_level=0, **kwargs) # Minimize m.migrad() return m.values
def calc_min_smearing(self, verbose=False): """Calculate minimum (optimal) smearing. Inputs: verbose: Print information to screen (Default = False) """ half_dDMmin = 0.5 * ALLOW_DMSTEPS[0] self.min_chan_smear = psr_utils.dm_smear(self.loDM+half_dDMmin, \ self.obs.chanwidth, self.obs.fctr) self.min_bw_smear = psr_utils.dm_smear(half_dDMmin, self.obs.BW, self.obs.fctr) self.min_total_smear = np.sqrt(2*self.obs.dt**2.0 + \ self.min_chan_smear**2.0 + \ self.min_bw_smear**2.0) self.best_resolution = max([self.req_resolution, self.min_chan_smear, \ self.min_bw_smear, self.obs.dt]) self.resolution = self.best_resolution if verbose: print print "Minimum total smearing : %.3g s" % self.min_total_smear print "--------------------------------------------" print "Minimum channel smearing : %.3g s" % self.min_chan_smear print "Minimum smearing across BW : %.3g s" % self.min_bw_smear print "Minimum sample time : %.3g s" % self.obs.dt print print "Setting the new 'best' resolution to : %.3g s" % self.best_resolution # See if the data is too high time resolution for our needs if (FF*self.min_chan_smear > self.obs.dt) or \ (self.resolution > self.obs.dt): if self.resolution > FF * self.min_chan_smear: if verbose: print " Note: resolution > dt (i.e. data is higher resolution than needed)" self.resolution = self.resolution else: if verbose: print " Note: min chan smearing > dt (i.e. data is higher resolution than needed)" self.resolution = FF * self.min_chan_smear
def _compute_rating(self, cand): """Return a rating for the candidate. The rating value encodes how close the candidate's period and DM are to that of a known pulsar. Input: cand: A Candidate object to rate. Output: value: The rating value. """ info = cand.get_from_cache('info') candp = info['bary_period'] canddm = info['dm'] ra = info['raj_deg'] dec = info['decj_deg'] pfd = cand.get_from_cache('pfd') diff_ra = np.abs(self.known_ras - ra) diff_dec = np.abs(self.known_decs - dec) ii_nearby = (diff_ra < 0.2) & (diff_dec < 0.2) knownps = self.known_periods[ii_nearby] knowndms = self.known_dms[ii_nearby] dp_smear_phase = np.inf * np.ones(knownps.size) ddms = np.abs(canddm - knowndms) bw = pfd.hifreq - pfd.lofreq fctr = 0.5 * (pfd.hifreq + pfd.lofreq) ddm_smear_phase = psr_utils.dm_smear(ddms, bw, fctr) / knownps if knownps.size: for b in range(1, M): dp_smear_sec = np.abs(candp * b - knownps) * pfd.T dp_smear_phase = np.min(np.vstack( (dp_smear_sec / knownps, dp_smear_phase)), axis=0) for rat in self.ratios: dp_smear_sec = np.abs(candp * b - knownps) * pfd.T dp_smear_phase = np.min(np.vstack( (dp_smear_sec / knownps, dp_smear_phase)), axis=0) smear_phase = np.min( np.sqrt(dp_smear_phase**2 + ddm_smear_phase**2)) #if smear_phase > 1: # print pfd.pfd_filename, smear_phase smear_phase = np.clip(smear_phase, 0, 10) else: # No nearby known pulsars smear_phase = 10 return smear_phase
def filter_on_effective_time_resolution(candidates, metadata, n_bins): ''' Reject pulsar candidates with fewer than n_bins bins across their profile. ''' out_cand_list = [] channel_bandwidth = metadata.channel_bandwidth central_frequency = ((metadata.n_channels/2) - 0.5) * channel_bandwidth +\ metadata.low_channel_central_freq for c in candidates: intra_channel_smearing = psr_utils.dm_smear(c.DM, channel_bandwidth, central_frequency) if c.p / intra_channel_smearing > n_bins: out_cand_list.append(c) print 'Filtering on effective time resolution:' print ' Removed %d out %d candidates.' % ( len(candidates) - len(out_cand_list), len(candidates)) return out_cand_list
def _compute_rating(self, cand): """Return a rating for the candidate. The rating value encodes how close the candidate's period and DM are to that of a known pulsar. Input: cand: A Candidate object to rate. Output: value: The rating value. """ info = cand.get_from_cache('info') candp = info['bary_period'] canddm = info['dm'] ra = info['raj_deg'] dec = info['decj_deg'] pfd = cand.get_from_cache('pfd') diff_ra = np.abs(self.known_ras - ra) diff_dec = np.abs(self.known_decs - dec) ii_nearby = (diff_ra < 0.2) & (diff_dec < 0.2) knownps = self.known_periods[ii_nearby] knowndms = self.known_dms[ii_nearby] dp_smear_phase = np.inf*np.ones(knownps.size) ddms = np.abs(canddm-knowndms) bw = pfd.hifreq-pfd.lofreq fctr = 0.5*(pfd.hifreq+pfd.lofreq) ddm_smear_phase = psr_utils.dm_smear(ddms, bw, fctr)/knownps if knownps.size: for b in range(1, M): dp_smear_sec = np.abs(candp*b-knownps)*pfd.T dp_smear_phase = np.min(np.vstack((dp_smear_sec/knownps, dp_smear_phase)), axis=0) for rat in self.ratios: dp_smear_sec = np.abs(candp*b-knownps)*pfd.T dp_smear_phase = np.min(np.vstack((dp_smear_sec/knownps, dp_smear_phase)), axis=0) smear_phase = np.min(np.sqrt(dp_smear_phase**2+ddm_smear_phase**2)) #if smear_phase > 1: # print pfd.pfd_filename, smear_phase smear_phase = np.clip(smear_phase, 0, 10) else: # No nearby known pulsars smear_phase = 10 return smear_phase
def __init__(self, ddplan, downsamp, loDM, dDM, numDMs=0, numsub=0, smearfact=2.0): """DDstep object constructor. Inputs: ddplan: DDplan object this DDstep is part of. downsamp: Downsampling factor. loDM: Low DM edge of this DDstep (pc cm-3) dDM: DM step size to use (pc cm-3) numDMs: Number of DMs. If numDMs=0 compute numDMs based on DM range and spacing. (Default: 0) numsub: Number of subbands to use. (Default: no subbanding). smearfact: Allowable smearing in a single channel, relative to other smearing contributions (Default: 2.0) """ self.ddplan = ddplan self.downsamp = downsamp self.loDM = loDM self.dDM = dDM self.numsub = numsub self.BW_smearing = psr_utils.dm_smear(dDM * 0.5, self.ddplan.obs.BW, self.ddplan.obs.fctr) self.numprepsub = 0 if numsub: # Calculate the maximum subband smearing we can handle DMs_per_prepsub = 2 while True: next_dsubDM = (DMs_per_prepsub + 2) * dDM next_ss = psr_utils.dm_smear(next_dsubDM * 0.5, self.ddplan.obs.BW / numsub, self.ddplan.obs.fctr) # The 0.8 is a small fudge factor to make sure that the subband # smearing is always the smallest contribution if next_ss > 0.8 * min(self.BW_smearing, self.ddplan.obs.dt * self.downsamp): self.dsubDM = DMs_per_prepsub * dDM self.DMs_per_prepsub = DMs_per_prepsub self.sub_smearing = psr_utils.dm_smear( self.dsubDM * 0.5, self.ddplan.obs.BW / self.numsub, self.ddplan.obs.fctr ) break DMs_per_prepsub += 2 else: self.dsubDM = dDM self.sub_smearing = 0.0 # Calculate the nominal DM to move to the next step cross_DM = self.DM_for_smearfact(smearfact) if cross_DM > self.ddplan.hiDM: cross_DM = self.ddplan.hiDM if numDMs == 0: self.numDMs = int(np.ceil((cross_DM - self.loDM) / self.dDM)) if numsub: self.numprepsub = int(np.ceil(self.numDMs * self.dDM / self.dsubDM)) self.numDMs = self.numprepsub * DMs_per_prepsub else: self.numDMs = numDMs self.hiDM = loDM + self.numDMs * dDM self.DMs = np.arange(self.numDMs, dtype="d") * self.dDM + self.loDM # Calculate a few more smearing values self.chan_smear = psr_utils.dm_smear(self.DMs, self.ddplan.obs.chanwidth, self.ddplan.obs.fctr) self.tot_smear = np.sqrt( (self.ddplan.obs.dt) ** 2.0 + (self.ddplan.obs.dt * self.downsamp) ** 2.0 + self.BW_smearing ** 2.0 + self.sub_smearing ** 2.0 + self.chan_smear ** 2.0 )
counterpart = j break # print f1,fwant if counterpart == False: print "Didn't find counterpart frequency for %f" % f0 sub.set_weight(i, 0.0) continue # else: # print counterpart,f1 # print f0, f1 # sys.exit() # print f0,f1 p = sub.get_folding_period() smear = (psr_utils.dm_smear(dm, chbw, f0) + psr_utils.dm_smear(dm, chbw, f1)) / p delay = (psr_utils.delay_from_DM(dm, f0) - psr_utils.delay_from_DM(dm, f1)) / p delay -= int(delay) if delay < -0.5: delay += 1.0 if delay > 0.5: delay -= 1.0 #print i, smear, delay for pol in range(2): if pol == 0: correction = pol0correction / 2.0 else:
def plot(self, fn=None): """Generate a plot for this dedispersion plan. Inputs: fn: Filename to save plot as. If None, show plot interactively. (Default: Show plot interactively.) """ fig = plt.figure(figsize=(11, 8.5)) ax = plt.axes() stepDMs = [] # Plot each dedispersion step for ii, (step, wf) in enumerate(zip(self.DDsteps, self.work_fracts)): stepDMs.append(step.DMs) DMspan = np.ptp(step.DMs) loDM = step.DMs.min() + DMspan * 0.02 hiDM = step.DMs.max() - DMspan * 0.02 midDM = step.DMs.min() + DMspan * 0.5 # Sample time plt.plot(step.DMs, np.zeros(step.numDMs)+step.ddplan.obs.dt*step.downsamp, \ '#33CC33', label=((ii and "_nolegend_") or "Sample Time (ms)")) # DM stepsize smearing plt.plot(step.DMs, np.zeros(step.numDMs)+step.BW_smearing, 'r', \ label=((ii and "_nolegend_") or "DM Stepsize Smearing")) if self.numsub: plt.plot(step.DMs, np.zeros(step.numDMs)+step.sub_smearing, '#993399', \ label=((ii and "_nolegend_") or "Subband Stepsize Smearing (# passes)")) plt.plot(step.DMs, step.tot_smear, 'k', \ label=((ii and "_nolegend_") or "Total Smearing")) # plot text plt.text(midDM, 1.1*np.median(step.tot_smear), \ "%d (%.1f%%)" % (step.numDMs, 100.0*wf), \ rotation='vertical', size='small', \ ha='center', va='bottom') plt.text(loDM, 0.85*step.ddplan.obs.dt*step.downsamp, \ "%g" % (1000*step.ddplan.obs.dt*step.downsamp), \ size='small', color='#33CC33', ha='left') plt.text(hiDM, 0.85*step.BW_smearing, \ "%g" % step.dDM, size='small', color='r', ha='right') if self.numsub: plt.text(midDM, 0.85*step.sub_smearing, \ "%g (%d)" % (step.dsubDM, step.numprepsub), \ size='small', color='#993399', ha='center') allDMs = np.concatenate(stepDMs) chan_smear = psr_utils.dm_smear(allDMs, self.obs.chanwidth, self.obs.fctr) bw_smear = psr_utils.dm_smear(ALLOW_DMSTEPS[0], self.obs.BW, self.obs.fctr) tot_smear = np.sqrt(2*self.obs.dt**2.0 + \ chan_smear**2.0 + \ bw_smear**2.0) plt.plot(allDMs, tot_smear, '#FF9933', label="Optimal Smearing") plt.plot(allDMs, chan_smear, 'b', label="Channel Smearing") # Add text above plot settings = r"$f_{ctr}$ = %g MHz" % self.obs.fctr if self.obs.dt < 1e-4: settings += r", dt = %g $\mu$s" % (self.obs.dt * 1e6) else: settings += r", dt = %g ms" % (self.obs.dt * 1000) settings += r", BW = %g MHz" % self.obs.BW settings += r", N$_{chan}$ = %d" % self.obs.numchan if self.numsub: settings += r", N$_{sub}$ = %d" % self.numsub if self.obs.numsamp: settings += r", N$_{samp}$ = %d" % self.obs.numsamp plt.figtext(0.05, 0.005, settings, \ ha='left', size='small') plt.yscale('log') plt.xlabel(r"Dispersion Measure (pc cm$^{-3}$)") plt.ylabel(r"Smearing (s)") plt.xlim(allDMs.min(), allDMs.max()) plt.ylim(0.3 * tot_smear.min(), 2.5 * tot_smear.max()) leg = plt.legend(loc='lower right') plt.setp(leg.texts, size='small') plt.setp(leg.legendHandles, linewidth=2) if fn is not None: # Save figure to file plt.savefig(fn, orientation='landscape', papertype='letter') else: # Show figure interactively def keypress(event): if event.key in ['q', 'Q']: plt.close() fig.canvas.mpl_connect('key_press_event', keypress) plt.show()
def plot(self, fn=None): """Generate a plot for this dedispersion plan. Inputs: fn: Filename to save plot as. If None, show plot interactively. (Default: Show plot interactively.) """ fig = plt.figure(figsize=(11, 8.5)) ax = plt.axes() stepDMs = [] # Plot each dedispersion step for ii, (step, wf) in enumerate(zip(self.DDsteps, self.work_fracts)): stepDMs.append(step.DMs) DMspan = np.ptp(step.DMs) loDM = step.DMs.min() + DMspan * 0.02 hiDM = step.DMs.max() - DMspan * 0.02 midDM = step.DMs.min() + DMspan * 0.5 # Sample time plt.plot( step.DMs, np.zeros(step.numDMs) + step.ddplan.obs.dt * step.downsamp, "#33CC33", label=((ii and "_nolegend_") or "Sample Time (ms)"), ) # DM stepsize smearing plt.plot( step.DMs, np.zeros(step.numDMs) + step.BW_smearing, "r", label=((ii and "_nolegend_") or "DM Stepsize Smearing"), ) if self.numsub: plt.plot( step.DMs, np.zeros(step.numDMs) + step.sub_smearing, "#993399", label=((ii and "_nolegend_") or "Subband Stepsize Smearing (# passes)"), ) plt.plot(step.DMs, step.tot_smear, "k", label=((ii and "_nolegend_") or "Total Smearing")) # plot text plt.text( midDM, 1.1 * np.median(step.tot_smear), "%d (%.1f%%)" % (step.numDMs, 100.0 * wf), rotation="vertical", size="small", ha="center", va="bottom", ) plt.text( loDM, 0.85 * step.ddplan.obs.dt * step.downsamp, "%g" % (1000 * step.ddplan.obs.dt * step.downsamp), size="small", color="#33CC33", ha="left", ) plt.text(hiDM, 0.85 * step.BW_smearing, "%g" % step.dDM, size="small", color="r", ha="right") if self.numsub: plt.text( midDM, 0.85 * step.sub_smearing, "%g (%d)" % (step.dsubDM, step.numprepsub), size="small", color="#993399", ha="center", ) allDMs = np.concatenate(stepDMs) chan_smear = psr_utils.dm_smear(allDMs, self.obs.chanwidth, self.obs.fctr) bw_smear = psr_utils.dm_smear(ALLOW_DMSTEPS[0], self.obs.BW, self.obs.fctr) tot_smear = np.sqrt(2 * self.obs.dt ** 2.0 + chan_smear ** 2.0 + bw_smear ** 2.0) plt.plot(allDMs, tot_smear, "#FF9933", label="Optimal Smearing") plt.plot(allDMs, chan_smear, "b", label="Channel Smearing") # Add text above plot settings = r"$f_{ctr}$ = %g MHz" % self.obs.fctr if self.obs.dt < 1e-4: settings += r", dt = %g $\mu$s" % (self.obs.dt * 1e6) else: settings += r", dt = %g ms" % (self.obs.dt * 1000) settings += r", BW = %g MHz" % self.obs.BW settings += r", N$_{chan}$ = %d" % self.obs.numchan if self.numsub: settings += r", N$_{sub}$ = %d" % self.numsub if self.obs.numsamp: settings += r", N$_{samp}$ = %d" % self.obs.numsamp plt.figtext(0.05, 0.005, settings, ha="left", size="small") plt.yscale("log") plt.xlabel(r"Dispersion Measure (pc cm$^{-3}$)") plt.ylabel(r"Smearing (s)") plt.xlim(allDMs.min(), allDMs.max()) plt.ylim(0.3 * tot_smear.min(), 2.5 * tot_smear.max()) leg = plt.legend(loc="lower right") plt.setp(leg.texts, size="small") plt.setp(leg.legendHandles, linewidth=2) if fn is not None: # Save figure to file plt.savefig(fn, orientation="landscape", papertype="letter") else: # Show figure interactively def keypress(event): if event.key in ["q", "Q"]: plt.close() fig.canvas.mpl_connect("key_press_event", keypress) plt.show()
def Multi_Gaussian_Ratings(pfd, debug=False): """ Calculate ratings that depend on a fit of multiple Gaussian profile components. Parameters ---------- pfd : class An instance of the prepfold.pfd class debug : boolean If True, plot the profile and best-fit Gaussians Returns ------- names : list A list of ratings names ratings : list A list of ratings values """ # The ratings names name1 = "Number_of_Gaussians" name2 = "Pulse_Width_Rating" # 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 best fold profile profile = N.sum(N.sum(pfd.profs, axis=1), axis=0) # Get the period from bestprof, if it exists if hasattr(pfd.bestprof, "p0"): P0 = pfd.bestprof.p0 # Otherwise use the barycentric or topocentric folding periods else: if pfd.bary_p1 != 0.0: P0 = pfd.bary_p1 elif pfd.topo_p1 != 0.0: P0 = pfd.topo_p1 # Get the center observing frequency f_ctr = (pfd.hifreq + pfd.lofreq)/2 # Fit up to MAX_GAUSSIANS Gaussians to the profile gaussian_params, red_chi2, ngaussians = \ PT.fit_gaussians_presto(profile, pfd.avgprof, N.sqrt(pfd.varprof), MAX_GAUSSIANS, F_STAT_THRESHOLD) if debug: phases = N.arange(pfd.proflen, dtype=N.float)/pfd.proflen gaussians = PT.make_gaussians_presto(gaussian_params, pfd.proflen) PL.plot(phases, profile) PL.plot(phases, gaussians) PL.show() # Create a list for storing the FWHMs of the Gaussians fwhms = [] # If we were able to fit at least one Gaussian... if ngaussians != 0: # Get and store the FWHM for each Gaussian for nn in xrange(ngaussians): fwhms.append(gaussian_params[1+3*nn+1]) # Calculate the DM smearing time dm_smear_sec = PU.dm_smear(pfd.bestdm, pfd.chan_wid, f_ctr) # Calculate the expected minimum pulse width width_phase = N.sqrt(dm_smear_sec**2 + pfd.dt**2)/P0 # Compare the expected minimum and actual pulse widths width_ratio = width_phase/min(fwhms) # If no Gaussians could be fit to the profile, store bogus metrics else: width_ratio = -1.0 # Store the ratings rating1 = ngaussians rating2 = width_ratio return [name1,name2],[rating1,rating2]
def Multi_Gaussian_Ratings(pfd, debug=False): """ Calculate ratings that depend on a fit of multiple Gaussian profile components. Parameters ---------- pfd : class An instance of the prepfold.pfd class debug : boolean If True, plot the profile and best-fit Gaussians Returns ------- names : list A list of ratings names ratings : list A list of ratings values """ # The ratings names name1 = "Number_of_Gaussians" name2 = "Pulse_Width_Rating" # 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 best fold profile profile = N.sum(N.sum(pfd.profs, axis=1), axis=0) # Get the period from bestprof, if it exists if hasattr(pfd.bestprof, "p0"): P0 = pfd.bestprof.p0 # Otherwise use the barycentric or topocentric folding periods else: if pfd.bary_p1 != 0.0: P0 = pfd.bary_p1 elif pfd.topo_p1 != 0.0: P0 = pfd.topo_p1 # Get the center observing frequency f_ctr = (pfd.hifreq + pfd.lofreq) / 2 # Fit up to MAX_GAUSSIANS Gaussians to the profile gaussian_params, red_chi2, ngaussians = \ PT.fit_gaussians_presto(profile, pfd.avgprof, N.sqrt(pfd.varprof), MAX_GAUSSIANS, F_STAT_THRESHOLD) if debug: phases = N.arange(pfd.proflen, dtype=N.float) / pfd.proflen gaussians = PT.make_gaussians_presto(gaussian_params, pfd.proflen) PL.plot(phases, profile) PL.plot(phases, gaussians) PL.show() # Create a list for storing the FWHMs of the Gaussians fwhms = [] # If we were able to fit at least one Gaussian... if ngaussians != 0: # Get and store the FWHM for each Gaussian for nn in xrange(ngaussians): fwhms.append(gaussian_params[1 + 3 * nn + 1]) # Calculate the DM smearing time dm_smear_sec = PU.dm_smear(pfd.bestdm, pfd.chan_wid, f_ctr) # Calculate the expected minimum pulse width width_phase = N.sqrt(dm_smear_sec**2 + pfd.dt**2) / P0 # Compare the expected minimum and actual pulse widths width_ratio = width_phase / min(fwhms) # If no Gaussians could be fit to the profile, store bogus metrics else: width_ratio = -1.0 # Store the ratings rating1 = ngaussians rating2 = width_ratio return [name1, name2], [rating1, rating2]
counterpart = j break # print f1,fwant if counterpart == False: print "Didn't find counterpart frequency for %f" % f0 sub.set_weight(i,0.0) continue # else: # print counterpart,f1 # print f0, f1 # sys.exit() # print f0,f1 p = sub.get_folding_period() smear = (psr_utils.dm_smear(dm,chbw,f0) + psr_utils.dm_smear(dm,chbw,f1)) / p delay = (psr_utils.delay_from_DM(dm,f0) - psr_utils.delay_from_DM(dm,f1)) / p delay -= int(delay) if delay<-0.5: delay += 1.0 if delay>0.5: delay -= 1.0 #print i, smear, delay for pol in range(2): if pol == 0: correction = pol0correction/2.0 else:
def __init__(self, loDM, hiDM, obs, numsub=0, resolution=0.0, verbose=False): """DDplan object constructor. Inputs: loDM: Low DM to consider (pc cm-3) hiDM: High DM to consider (pc cm-3) obs: Observation object numsub: Number of subbands to use (Default = Don't subband) resolution: Acceptable smearing in ms (Default = Least smearing possible) verbose: Print information to screen (Default = False) """ self.loDM = loDM self.hiDM = hiDM self.obs = obs self.numsub = numsub self.req_resolution = resolution * 0.001 # In seconds self.current_downfact = self.obs.allow_factors[0] self.current_dDM = ALLOW_DMSTEPS[0] self.DDsteps = [] # list of dedispersion steps # Calculate optimal smearing self.calc_min_smearing(verbose=verbose) # Calculate initial downsampling while (self.obs.dt * self.get_next_downfact()) < self.resolution: self.current_downfact = self.get_next_downfact() if verbose: print " New dt is %d x %.12g s = %.12g s" % ( self.current_downfact, self.obs.dt, self.current_downfact * self.obs.dt, ) # Calculate the appropriate initial dDM dDM = guess_DMstep(self.obs.dt * self.current_downfact, 0.5 * self.obs.BW, self.obs.fctr) if verbose: print "Best guess for optimal initial dDM is %.3f" % dDM while self.get_next_dDM() < dDM: self.current_dDM = self.get_next_dDM() self.DDsteps.append( DDstep(self, self.current_downfact, self.loDM, self.current_dDM, numsub=self.numsub, smearfact=SMEARFACT) ) # Calculate the next steps while self.DDsteps[-1].hiDM < self.hiDM: # Determine the new downsample factor self.current_downfact = self.get_next_downfact() eff_dt = self.obs.dt * self.current_downfact # Determine the new DM step while psr_utils.dm_smear(0.5 * self.get_next_dDM(), self.obs.BW, self.obs.fctr) < FF * eff_dt: self.current_dDM = self.get_next_dDM() # Get the next step self.DDsteps.append( DDstep( self, self.current_downfact, self.DDsteps[-1].hiDM, self.current_dDM, numsub=self.numsub, smearfact=SMEARFACT, ) ) # Calculate the predicted amount of time that will be spent in searching # this batch of DMs as a fraction of the total wfs = [step.numDMs / float(step.downsamp) for step in self.DDsteps] self.work_fracts = np.asarray(wfs) / np.sum(wfs)
def apply_dm(inprof, period, dm, chan_width, freqs, tsamp, \ do_delay=True, do_smear=True, do_scatter=True, verbose=True): """Given a profile apply DM delays, smearing, and scattering within each channel as is appropriate for the given params. Inputs: inprof: The profile to modify. period: The profiles period (in seconds) dm: The DM (in pc cm-3) chan_width: The width of each channel (in MHz) freqs: The list of frequencies (in MHz) tsamp: Sample time of the recipient filterbank file (in seconds). do_delay: Boolean, if True apply DM delays to each channel. The highest freq channel is not shifted. (Default: True) do_smear: Boolean, if True apply DM smearing to each channel. (Default: True) do_scatter: Boolean, if True apply scattering to each channel. (Default: True) Outputs: vecprof: The delayed and smeared VectorProfile. """ weq = inprof.get_equivalent_width() nfreqs = len(freqs) if verbose: print "Applying DM to profile (DM = %.2f; %d channels)..." % \ (dm, nfreqs) # A list of profiles, one for each channel profiles = [] if dm <= 0: warnings.warn("DM will not be applied because it is 0 (or smaller?!)") do_delay = False do_smear = False do_scatter = False if do_delay: phasedelays = get_phasedelays(dm, freqs, period) else: phasedelays = np.zeros(nfreqs) # Prepare for smear campaign smeartimes = psr_utils.dm_smear(dm, abs(chan_width), freqs) # In seconds smearphases = smeartimes/period # Prepare to scatter scattertimes = psr_utils.pulse_broadening(dm, freqs)*1e-3 # In seconds scatterphases = scattertimes/period if DEBUG: for ichan, (freq, smear, scatt, delay) in \ enumerate(zip(freqs, smearphases, scatterphases, phasedelays)): print " Chan #%d - Freq: %.3f MHz -- " \ "Smearing, scattering, delay (all in phase): " \ "%g, %g, %g" % (ichan, freq, smear, scatt, delay) oldprogress = 0 sys.stdout.write(" %3.0f %%\r" % oldprogress) sys.stdout.flush() # ylim = None # ylim2 = None # ylim3 = None # ylim4 = None # ylim5 = None for ii, (delayphs, smearphs, scattphs) in \ enumerate(zip(phasedelays, smearphases, scatterphases)): ######### # DEBUG: plot all profiles # plt.clf() # ax = plt.subplot(5,1,1) # inprof.plot() # if ylim is not None: # ax.set_ylim(ylim) # else: # ylim = ax.get_ylim() if do_smear and not ((smearphs < 0.2*weq) or (smearphs < (tsamp/period))): # Only smear if requested and smearing-phase is large enough # bc = boxcar_factory(smearphs, delayphs) # ax2 = plt.subplot(5,1,2,sharex=ax) # bc.plot() # if ylim2 is not None: # ax2.set_ylim(ylim2) # else: # ylim2 = ax2.get_ylim() if DEBUG: print "Smearing" tmpprof = inprof.smear(smearphs, delayphs, npts=NUMPOINTS) else: tmpprof = inprof.delay(delayphs) phs = np.linspace(0, 1, NUMPOINTS+1) tmpprof = SplineProfile(tmpprof(phs)) # ax3 = plt.subplot(5,1,3,sharex=ax) # if ylim3 is not None: # ax3.set_ylim(ylim3) # else: # ylim3 = ax3.get_ylim() # tmpprof.plot() if do_scatter and not ((scattphs < 0.2*weq) or (scattphs < (tsamp/period))): # Only scatter if requested and scattering-phase is large enough # ex = exponential_factory(scattphs) # ax4 = plt.subplot(5,1,4,sharex=ax) # ex.plot() # if ylim4 is not None: # ax4.set_ylim(ylim4) # else: # ylim4 = ax4.get_ylim() if DEBUG: print "Scattering" tmpprof = tmpprof.scatter(scattphs, npts=NUMPOINTS) # ax5 = plt.subplot(5,1,5,sharex=ax) # tmpprof.plot() # if ylim5 is not None: # ax5.set_ylim(ylim5) # else: # ylim5 = ax5.get_ylim() profiles.append(tmpprof) # plt.xlim(0,1) # plt.xlabel("Phase") # plt.suptitle("Prof %d (%f MHz)" % (ii, freqs[ii])) # plt.savefig("prof%d.png" % ii) ######### # Print progress to screen progress = int(100.0*ii/nfreqs) if progress > oldprogress: sys.stdout.write(" %3.0f %%\r" % progress) sys.stdout.flush() oldprogress = progress sys.stdout.write("Done \n") sys.stdout.flush() dispersedprof = DispersedProfile(profiles, dm=dm, freqs=freqs, period=period, intrinsic=inprof, delayed=do_delay) return dispersedprof
def __init__(self, loDM, hiDM, obs, numsub=0, resolution=0.0, \ verbose=False): """DDplan object constructor. Inputs: loDM: Low DM to consider (pc cm-3) hiDM: High DM to consider (pc cm-3) obs: Observation object numsub: Number of subbands to use (Default = Don't subband) resolution: Acceptable smearing in ms (Default = Least smearing possible) verbose: Print information to screen (Default = False) """ self.loDM = loDM self.hiDM = hiDM self.obs = obs self.numsub = numsub self.req_resolution = resolution * 0.001 # In seconds self.current_downfact = self.obs.allow_factors[0] self.current_dDM = ALLOW_DMSTEPS[0] self.DDsteps = [] # list of dedispersion steps # Calculate optimal smearing self.calc_min_smearing(verbose=verbose) # Calculate initial downsampling while (self.obs.dt * self.get_next_downfact()) < self.resolution: self.current_downfact = self.get_next_downfact() if verbose: print " New dt is %d x %.12g s = %.12g s" % \ (self.current_downfact, self.obs.dt, \ self.current_downfact*self.obs.dt) # Calculate the appropriate initial dDM dDM = guess_DMstep(self.obs.dt*self.current_downfact, \ 0.5*self.obs.BW, self.obs.fctr) if verbose: print "Best guess for optimal initial dDM is %.3f" % dDM while (self.get_next_dDM() < dDM): self.current_dDM = self.get_next_dDM() self.DDsteps.append(DDstep(self, self.current_downfact, \ self.loDM, self.current_dDM, \ numsub=self.numsub, \ smearfact=SMEARFACT)) # Calculate the next steps while self.DDsteps[-1].hiDM < self.hiDM: # Determine the new downsample factor self.current_downfact = self.get_next_downfact() eff_dt = self.obs.dt * self.current_downfact # Determine the new DM step while psr_utils.dm_smear(0.5*self.get_next_dDM(), self.obs.BW, \ self.obs.fctr) < FF*eff_dt: self.current_dDM = self.get_next_dDM() # Get the next step self.DDsteps.append(DDstep(self, self.current_downfact, \ self.DDsteps[-1].hiDM, \ self.current_dDM, \ numsub=self.numsub, \ smearfact=SMEARFACT)) # Calculate the predicted amount of time that will be spent in searching # this batch of DMs as a fraction of the total wfs = [step.numDMs / float(step.downsamp) for step in self.DDsteps] self.work_fracts = np.asarray(wfs) / np.sum(wfs)
def apply_dm(inprof, period, dm, chan_width, freqs, tsamp, \ do_delay=True, do_smear=True, do_scatter=True, verbose=True): """Given a profile apply DM delays, smearing, and scattering within each channel as is appropriate for the given params. Inputs: inprof: The profile to modify. period: The profiles period (in seconds) dm: The DM (in pc cm-3) chan_width: The width of each channel (in MHz) freqs: The list of frequencies (in MHz) tsamp: Sample time of the recipient filterbank file (in seconds). do_delay: Boolean, if True apply DM delays to each channel. The highest freq channel is not shifted. (Default: True) do_smear: Boolean, if True apply DM smearing to each channel. (Default: True) do_scatter: Boolean, if True apply scattering to each channel. (Default: True) Outputs: vecprof: The delayed and smeared VectorProfile. """ weq = inprof.get_equivalent_width() nfreqs = len(freqs) if verbose: print("Applying DM to profile (DM = %.2f; %d channels)..." % \ (dm, nfreqs)) # A list of profiles, one for each channel profiles = [] if dm <= 0: warnings.warn("DM will not be applied because it is 0 (or smaller?!)") do_delay = False do_smear = False do_scatter = False if do_delay: phasedelays = get_phasedelays(dm, freqs, period) else: phasedelays = np.zeros(nfreqs) # Prepare for smear campaign smeartimes = psr_utils.dm_smear(dm, abs(chan_width), freqs) # In seconds smearphases = smeartimes/period # Prepare to scatter scattertimes = psr_utils.pulse_broadening(dm, freqs)*1e-3 # In seconds scatterphases = scattertimes/period if DEBUG: for ichan, (freq, smear, scatt, delay) in \ enumerate(zip(freqs, smearphases, scatterphases, phasedelays)): print(" Chan #%d - Freq: %.3f MHz -- " \ "Smearing, scattering, delay (all in phase): " \ "%g, %g, %g" % (ichan, freq, smear, scatt, delay)) oldprogress = 0 sys.stdout.write(" %3.0f %%\r" % oldprogress) sys.stdout.flush() # ylim = None # ylim2 = None # ylim3 = None # ylim4 = None # ylim5 = None for ii, (delayphs, smearphs, scattphs) in \ enumerate(zip(phasedelays, smearphases, scatterphases)): ######### # DEBUG: plot all profiles # plt.clf() # ax = plt.subplot(5,1,1) # inprof.plot() # if ylim is not None: # ax.set_ylim(ylim) # else: # ylim = ax.get_ylim() if do_smear and not ((smearphs < 0.2*weq) or (smearphs < (tsamp/period))): # Only smear if requested and smearing-phase is large enough # bc = boxcar_factory(smearphs, delayphs) # ax2 = plt.subplot(5,1,2,sharex=ax) # bc.plot() # if ylim2 is not None: # ax2.set_ylim(ylim2) # else: # ylim2 = ax2.get_ylim() if DEBUG: print("Smearing") tmpprof = inprof.smear(smearphs, delayphs, npts=NUMPOINTS) else: tmpprof = inprof.delay(delayphs) phs = np.linspace(0, 1, NUMPOINTS+1) tmpprof = SplineProfile(tmpprof(phs)) # ax3 = plt.subplot(5,1,3,sharex=ax) # if ylim3 is not None: # ax3.set_ylim(ylim3) # else: # ylim3 = ax3.get_ylim() # tmpprof.plot() if do_scatter and not ((scattphs < 0.2*weq) or (scattphs < (tsamp/period))): # Only scatter if requested and scattering-phase is large enough # ex = exponential_factory(scattphs) # ax4 = plt.subplot(5,1,4,sharex=ax) # ex.plot() # if ylim4 is not None: # ax4.set_ylim(ylim4) # else: # ylim4 = ax4.get_ylim() if DEBUG: print("Scattering") tmpprof = tmpprof.scatter(scattphs, npts=NUMPOINTS) # ax5 = plt.subplot(5,1,5,sharex=ax) # tmpprof.plot() # if ylim5 is not None: # ax5.set_ylim(ylim5) # else: # ylim5 = ax5.get_ylim() profiles.append(tmpprof) # plt.xlim(0,1) # plt.xlabel("Phase") # plt.suptitle("Prof %d (%f MHz)" % (ii, freqs[ii])) # plt.savefig("prof%d.png" % ii) ######### # Print progress to screen progress = int(100.0*ii/nfreqs) if progress > oldprogress: sys.stdout.write(" %3.0f %%\r" % progress) sys.stdout.flush() oldprogress = progress sys.stdout.write("Done \n") sys.stdout.flush() dispersedprof = DispersedProfile(profiles, dm=dm, freqs=freqs, period=period, intrinsic=inprof, delayed=do_delay) return dispersedprof
def __init__(self, ddplan, downsamp, loDM, dDM, \ numDMs=0, numsub=0, smearfact=2.0): """DDstep object constructor. Inputs: ddplan: DDplan object this DDstep is part of. downsamp: Downsampling factor. loDM: Low DM edge of this DDstep (pc cm-3) dDM: DM step size to use (pc cm-3) numDMs: Number of DMs. If numDMs=0 compute numDMs based on DM range and spacing. (Default: 0) numsub: Number of subbands to use. (Default: no subbanding). smearfact: Allowable smearing in a single channel, relative to other smearing contributions (Default: 2.0) """ self.ddplan = ddplan self.downsamp = downsamp self.loDM = loDM self.dDM = dDM self.numsub = numsub self.BW_smearing = psr_utils.dm_smear(dDM*0.5, self.ddplan.obs.BW, \ self.ddplan.obs.fctr) self.numprepsub = 0 if numsub: # Calculate the maximum subband smearing we can handle DMs_per_prepsub = 2 while True: next_dsubDM = (DMs_per_prepsub + 2) * dDM next_ss = psr_utils.dm_smear(next_dsubDM*0.5, \ self.ddplan.obs.BW/numsub, \ self.ddplan.obs.fctr) # The 0.8 is a small fudge factor to make sure that the subband # smearing is always the smallest contribution if next_ss > 0.8*min(self.BW_smearing, \ self.ddplan.obs.dt*self.downsamp): self.dsubDM = DMs_per_prepsub * dDM self.DMs_per_prepsub = DMs_per_prepsub self.sub_smearing = psr_utils.dm_smear(self.dsubDM*0.5, self.ddplan.obs.BW/self.numsub, \ self.ddplan.obs.fctr) break DMs_per_prepsub += 2 else: self.dsubDM = dDM self.sub_smearing = 0.0 # Calculate the nominal DM to move to the next step cross_DM = self.DM_for_smearfact(smearfact) if cross_DM > self.ddplan.hiDM: cross_DM = self.ddplan.hiDM if numDMs == 0: self.numDMs = int(np.ceil((cross_DM - self.loDM) / self.dDM)) if numsub: self.numprepsub = int( np.ceil(self.numDMs * self.dDM / self.dsubDM)) self.numDMs = self.numprepsub * DMs_per_prepsub else: self.numDMs = numDMs self.hiDM = loDM + self.numDMs * dDM self.DMs = np.arange(self.numDMs, dtype='d') * self.dDM + self.loDM # Calculate a few more smearing values self.chan_smear = psr_utils.dm_smear(self.DMs, \ self.ddplan.obs.chanwidth, \ self.ddplan.obs.fctr) self.tot_smear = np.sqrt((self.ddplan.obs.dt)**2.0 + \ (self.ddplan.obs.dt*self.downsamp)**2.0 + \ self.BW_smearing**2.0 + \ self.sub_smearing**2.0 + \ self.chan_smear**2.0)