def _compute_rating(self, cand): """ """ profile = utils.get_scaled_profile(cand.profile, cand.pfd.varprof) mgauss = cand.multigaussfit chi2 = mgauss.get_chisqr(profile) dof = mgauss.get_dof(len(profile)) return chi2 / dof
def _compute_rating(self, cand): """ """ profile = utils.get_scaled_profile(cand.profile, cand.pfd.varprof) mgauss = cand.multigaussfit chi2 = mgauss.get_chisqr(profile) dof = mgauss.get_dof(len(profile)) return chi2/dof
def _compute_rating(self, cand): """ """ prof = cand.get_from_cache('profile') pfd = cand.get_from_cache('pfd') mgauss = cand.get_from_cache('multigaussfit') profile = utils.get_scaled_profile(prof, pfd.varprof) chi2 = mgauss.get_chisqr(profile) dof = mgauss.get_dof(len(profile)) return chi2/dof
def _compute_rating(self, cand): """ """ prof = cand.get_from_cache('profile') pfd = cand.get_from_cache('pfd') mgauss = cand.get_from_cache('multigaussfit') profile = utils.get_scaled_profile(prof, pfd.varprof) chi2 = mgauss.get_chisqr(profile) dof = mgauss.get_dof(len(profile)) return chi2 / dof
def _compute_rating(self, cand): """Return a rating for the candidate. The rating value is the reduced chi2 of the gaussian function fit to the candidate's profile. Input: cand: An SPCandidate object to rate. Output: value: The rating value. """ profile = utils.get_scaled_profile(cand.profile, cand.spd.varprof) sgauss = cand.gaussfit chi2 = sgauss.get_chisqr(profile) dof = sgauss.get_dof(len(profile)) return chi2/dof
def _compute_rating(self, cand): """Return a rating for the candidate. The rating value is the reduced chi2 of the gaussian function fit to the candidate's profile. Input: cand: An SPCandidate object to rate. Output: value: The rating value. """ profile = utils.get_scaled_profile(cand.profile, cand.spd.varprof) sgauss = cand.gaussfit chi2 = sgauss.get_chisqr(profile) dof = sgauss.get_dof(len(profile)) return chi2 / dof
def _compute_rating(self, cand): """Return a rating for the candidate. The rating value is the reduced chi2 of the gaussian function fit to the candidate's profile. Input: cand: A Candidate object to rate. Output: value: The rating value. """ prof = cand.get_from_cache('profile') pfd = cand.get_from_cache('pfd') sgauss = cand.get_from_cache('singlegaussfit') profile = utils.get_scaled_profile(prof, pfd.varprof) chi2 = sgauss.get_chisqr(profile) dof = sgauss.get_dof(len(profile)) return chi2/dof
def _compute_data(self, cand): """Fit the candidate's profile with multiple gaussian components and return the fit's parameters. Input: cand: A ratings2.0 SPCandidate object. Output: multigaussfit: The corresponding fit. A MultiGaussFit object. """ data = utils.get_scaled_profile(cand.profile, cand.spd.varprof) # Initialize some starting values nbins = len(data) trial_params = [0.0] amplitude = max(data[(0.1 * nbins):(0.4 * nbins)]) fwhm = 0.02 # full window should be 50 times estimated pulse width phase = 0.25 # this is where the single pulse should be placed trial_params.append(amplitude) trial_params.append(fwhm) trial_params.append(phase) from scipy.optimize import leastsq def func(params): #print "DEBUG: params", params # since this is single gaussian, params is just [offset, amp, std, phs] fit = utils.multigaussfit_from_paramlist(params) return fit.get_resids(data) new_params, status = leastsq(func, trial_params) if status not in (1, 2, 3, 4): raise utils.RatingError("Status returned by " \ "scipy.optimize.leastsq (%d) " \ "indicates the fit failed!" % status) new_fit = utils.multigaussfit_from_paramlist(new_params) return new_fit
def _compute_data(self, cand): """Fit the candidate's profile with multiple gaussian components and return the fit's parameters. Input: cand: A ratings2.0 SPCandidate object. Output: multigaussfit: The corresponding fit. A MultiGaussFit object. """ data = utils.get_scaled_profile(cand.profile, cand.spd.varprof) # Initialize some starting values nbins = len(data) trial_params = [0.0] amplitude = max(data[(0.1*nbins):(0.4*nbins)]) fwhm = 0.02 # full window should be 50 times estimated pulse width phase = 0.25 # this is where the single pulse should be placed trial_params.append(amplitude) trial_params.append(fwhm) trial_params.append(phase) from scipy.optimize import leastsq def func(params): #print "DEBUG: params", params # since this is single gaussian, params is just [offset, amp, std, phs] fit = utils.multigaussfit_from_paramlist(params) return fit.get_resids(data) new_params, status = leastsq(func, trial_params) if status not in (1,2,3,4): raise utils.RatingError("Status returned by " \ "scipy.optimize.leastsq (%d) " \ "indicates the fit failed!" % status) new_fit = utils.multigaussfit_from_paramlist(new_params) return new_fit
def _compute_data(self, cand): """Fit the candidate's profile with multiple gaussian components and return the fit's parameters. Input: cand: A ratings2.0 Candidate object. Output: multigaussfit: The corresponding fit. A MultiGaussFit object. """ prof = cand.get_from_cache('profile') pfd = cand.get_from_cache('pfd') data = utils.get_scaled_profile(prof, pfd.varprof) # Initialize some starting values nbins = len(data) ngaussians = 0 # After normalization the first parameter (offset) should be close to zero prev_params = [0.0] # Nothing fit yet, so residuals are just the data values prev_residuals = data - np.zeros_like(data) # No need to normalize chi^2 by variance since we already did that to the # data prev_chi2 = sum(prev_residuals*prev_residuals) prev_dof = nbins fit = True # We will now start fitting Gaussian profile components until the # additional components are no longer statistically needed to improve the # fit. The starting parameter guesses for each new component will come # from the highest remaining residual and from the previous best-fit values # for previous components while fit: ngaussians += 1 # Update values based on results of previous run trial_params = list(prev_params) # Guess the parameters for the next profile component amplitude = max(prev_residuals) # Base FWHM on stats.norm normalization fwhm = 2*np.sqrt(2*np.log(2))/(np.sqrt(2*np.pi)*amplitude) phase = np.argmax(prev_residuals)/float(nbins) trial_params.append(amplitude) trial_params.append(fwhm) trial_params.append(phase) if self.USE_MPFIT: # params_dict is used by mpfit to get initial values and constraints on # parameters params_dict = [] for ii,param in enumerate(trial_params): if ii == 0: # The first parameter is the offset, which can be negative and # should be allowed to vary more params_dict.append({"value" : param, "fixed" : False, "limited": [False,False], "limits" : [0.0,0.0]}) elif (ii - 1)%3 == 1: # This is the FWHM, and is allowed to vary between # 1/nbins and 1.0 params_dict.append({"value" : param, "fixed" : False, "limited": [True, True], "limits" : [1.0/nbins, 1.0]}) else: # Limits are set assuming that our initial guesses were correct # to within 25%... params_dict.append({"value" : param, "fixed" : False, "limited": [True,True], "limits" : [0.25*param,1.75*param]}) # Define the fitting function for mpfit def func(params, fjac=None, errs=None): fit = utils.multigaussfit_from_paramlist(params) # Return values are [status, residuals] return [0, fit.get_resids(data)] # Now fit mpfit_out = mpfit.mpfit(func, parinfo=params_dict, quiet=True) # Store the new best-fit parameters new_params = mpfit_out.params else: import scipy.optimize def func(params): #print "DEBUG: params", params fit = utils.multigaussfit_from_paramlist(params) return fit.get_resids(data) new_params, status = scipy.optimize.leastsq(func, trial_params) if status not in (1,2,3,4): raise utils.RatingError("Status returned by " \ "scipy.optimize.leastsq (%d) " \ "indicates the fit failed!" % status) # Calculate the new residuals and statistics new_fit = utils.multigaussfit_from_paramlist(new_params) #print "DEBUG: new_fit", new_fit new_residuals = new_fit.get_resids(data) new_chi2 = new_fit.get_chisqr(data) new_dof = new_fit.get_dof(len(data)) # Degrees-of-freedom # Calculate the F-statistic for the fit, i.e. the probability that the # additional profile component is /not/ required by the data F_stat = psr_utils.Ftest(prev_chi2, prev_dof, \ new_chi2, new_dof) # If the F-test probability is greater than some threshold, then the # additional Gaussian did not significantly improve the fit and we # should stop. The nan test is needed because if the fit is /worse/ # then Ftest doesn't return a valid number. Also stop if we reach # the maximum number of Gaussian profile components. Stop if the # fwhm of the added component is greater than 1.0 if F_stat > self.F_stat_threshold or np.isnan(F_stat) \ or ngaussians > self.max_gaussians \ or new_fit.components[-1].fwhm > 1.0 \ or new_fit.components[-1].fwhm < 1.0/nbins: fit = False # Otherwise, keep fitting and update the parameters for the next pass else: fit = True prev_params = new_params prev_residuals = new_residuals prev_chi2 = new_chi2 prev_dof = new_dof # We stop when a fit is no longer needed, so we have to return the values # from the /previous/ run (otherwise we return the unneeded fit) #print "DEBUG: prev_params", prev_params finalfit = utils.multigaussfit_from_paramlist(prev_params) #print "DEBUG: finalfit", finalfit return finalfit
def main(): pfdfn = sys.argv[1] pfd = prepfold.pfd(pfdfn) cand = candidate.Candidate(pfd.topo_p1, pfd.bary_p1, pfd.bestdm, \ psr_utils.ra_to_rad(pfd.rastr)*psr_utils.RADTODEG, \ psr_utils.dec_to_rad(pfd.decstr)*psr_utils.RADTODEG, \ pfdfn) print "Loaded %s" % cand.pfdfn print " Best topo period (s): %f" % cand.topo_period print " Best bary period (s): %f" % cand.bary_period print " Best DM (cm^-3/pc): %f" % cand.dm print " RA (J2000 - deg): %f" % cand.raj_deg print " Dec (J2000 - deg): %f" % cand.decj_deg print "-"*10 pprint.pprint(cand.__dict__) print "-"*10 intstats.add_data(cand) print "Added subint stats to cand" pprint.pprint(cand.__dict__) print "-"*10 print "Subint stats object:" pprint.pprint(cand.subint_stats.__dict__) print "-"*10 print "Sub-int Stats:" print "On-fraction (area): %g" % cand.subint_stats.get_on_frac() print "On-fraction (peak): %g" % cand.subint_stats.get_peak_on_frac() print "Area SNR stddev: %g" % cand.subint_stats.get_snr_stddev() print "Peak SNR stddev: %g" % cand.subint_stats.get_peak_snr_stddev() print "Avg correlation coefficient: %g" % cand.subint_stats.get_avg_corrcoef() mgauss = cand.multigaussfit tvph = cand.time_vs_phase onpulse_region = mgauss.get_onpulse_region(tvph.nbin) offpulse_region = np.bitwise_not(onpulse_region) m = np.ma.masked_array(onpulse_region, mask=offpulse_region) onpulse_ranges = np.ma.notmasked_contiguous(m) print onpulse_ranges prof = utils.get_scaled_profile(cand.profile, cand.pfd.varprof) imax = plt.axes([0.1,0.1,0.5,0.7]) plt.imshow(scale2d(tvph.data), interpolation='nearest', \ aspect='auto', origin='lower', cmap=matplotlib.cm.gist_yarg) for opr in onpulse_ranges: onpulse_bin = (opr.start, opr.stop) if onpulse_bin[0] < onpulse_bin[1]: plt.axvspan(onpulse_bin[0], onpulse_bin[1]+1, fc='g', alpha=0.2, lw=0) else: plt.axvspan(onpulse_bin[0], tvph.nbin, fc='g', alpha=0.2, lw=0) plt.axvspan(-0.5, onpulse_bin[1]+1, fc='g', alpha=0.2, lw=0) plt.axes([0.1,0.8,0.5,0.15], sharex=imax) plt.plot(prof, 'k-', label='Profile') plt.plot(mgauss.make_gaussians(len(prof)), 'r--', label='Fit') for ii, opr in enumerate(onpulse_ranges): onpulse_bin = (opr.start, opr.stop) if ii == 0: lbl = 'On-pulse' else: lbl = '_nolabel_' if onpulse_bin[0] < onpulse_bin[1]: plt.axvspan(onpulse_bin[0], onpulse_bin[1]+1, fc='g', alpha=0.2, lw=0, label=lbl) else: plt.axvspan(onpulse_bin[0], tvph.nbin, fc='g', alpha=0.2, lw=0, label=lbl) plt.axvspan(-0.5, onpulse_bin[1]+1, fc='g', alpha=0.2, lw=0, label='_nolabel_') plt.legend(loc='best', prop=dict(size='xx-small')) plt.axes([0.6,0.1,0.15,0.7], sharey=imax) snrs = cand.subint_stats.snrs plt.plot(snrs, np.arange(len(snrs)), 'mo', label='SNR (area)') plt.axvline(5.0, c='m', ls='--', lw=2) peaksnrs = cand.subint_stats.peak_snrs plt.plot(peaksnrs, np.arange(len(peaksnrs)), 'cD', label='SNR (peak)') plt.axvline(3.0, c='c', ls='--', lw=2) plt.legend(loc='best', prop=dict(size='xx-small')) plt.axes([0.75,0.1,0.15,0.7], sharey=imax) corrcoefs = cand.subint_stats.corr_coefs plt.plot(corrcoefs, np.arange(len(corrcoefs)), 'k.') imax.set_xlim(-0.5,tvph.nbin-0.5) imax.set_ylim(-0.5,tvph.nsubint-0.5) plt.show()
def _compute_data(self, cand): """Fit the candidate's profile with multiple gaussian components and return the fit's parameters. Input: cand: A ratings2.0 Candidate object. Output: multigaussfit: The corresponding fit. A MultiGaussFit object. """ prof = cand.get_from_cache('profile') pfd = cand.get_from_cache('pfd') data = utils.get_scaled_profile(prof, pfd.varprof) # Initialize some starting values nbins = len(data) ngaussians = 0 # After normalization the first parameter (offset) should be close to zero prev_params = [0.0] # Nothing fit yet, so residuals are just the data values prev_residuals = data - np.zeros_like(data) # No need to normalize chi^2 by variance since we already did that to the # data prev_chi2 = sum(prev_residuals * prev_residuals) prev_dof = nbins fit = True # We will now start fitting Gaussian profile components until the # additional components are no longer statistically needed to improve the # fit. The starting parameter guesses for each new component will come # from the highest remaining residual and from the previous best-fit values # for previous components while fit: ngaussians += 1 # Update values based on results of previous run trial_params = list(prev_params) # Guess the parameters for the next profile component amplitude = max(prev_residuals) # Base FWHM on stats.norm normalization fwhm = 2 * np.sqrt( 2 * np.log(2)) / (np.sqrt(2 * np.pi) * amplitude) phase = np.argmax(prev_residuals) / float(nbins) trial_params.append(amplitude) trial_params.append(fwhm) trial_params.append(phase) if self.USE_MPFIT: # params_dict is used by mpfit to get initial values and constraints on # parameters params_dict = [] for ii, param in enumerate(trial_params): if ii == 0: # The first parameter is the offset, which can be negative and # should be allowed to vary more params_dict.append({ "value": param, "fixed": False, "limited": [False, False], "limits": [0.0, 0.0] }) elif (ii - 1) % 3 == 1: # This is the FWHM, and is allowed to vary between # 1/nbins and 1.0 params_dict.append({ "value": param, "fixed": False, "limited": [True, True], "limits": [1.0 / nbins, 1.0] }) else: # Limits are set assuming that our initial guesses were correct # to within 25%... params_dict.append({ "value": param, "fixed": False, "limited": [True, True], "limits": [0.25 * param, 1.75 * param] }) # Define the fitting function for mpfit def func(params, fjac=None, errs=None): fit = utils.multigaussfit_from_paramlist(params) # Return values are [status, residuals] return [0, fit.get_resids(data)] # Now fit mpfit_out = mpfit.mpfit(func, parinfo=params_dict, quiet=True) # Store the new best-fit parameters new_params = mpfit_out.params else: import scipy.optimize def func(params): #print "DEBUG: params", params fit = utils.multigaussfit_from_paramlist(params) return fit.get_resids(data) new_params, status = scipy.optimize.leastsq(func, trial_params) if status not in (1, 2, 3, 4): raise utils.RatingError("Status returned by " \ "scipy.optimize.leastsq (%d) " \ "indicates the fit failed!" % status) # Calculate the new residuals and statistics new_fit = utils.multigaussfit_from_paramlist(new_params) #print "DEBUG: new_fit", new_fit new_residuals = new_fit.get_resids(data) new_chi2 = new_fit.get_chisqr(data) new_dof = new_fit.get_dof(len(data)) # Degrees-of-freedom # Calculate the F-statistic for the fit, i.e. the probability that the # additional profile component is /not/ required by the data F_stat = psr_utils.Ftest(prev_chi2, prev_dof, \ new_chi2, new_dof) # If the F-test probability is greater than some threshold, then the # additional Gaussian did not significantly improve the fit and we # should stop. The nan test is needed because if the fit is /worse/ # then Ftest doesn't return a valid number. Also stop if we reach # the maximum number of Gaussian profile components. Stop if the # fwhm of the added component is greater than 1.0 if F_stat > self.F_stat_threshold or np.isnan(F_stat) \ or ngaussians > self.max_gaussians \ or new_fit.components[-1].fwhm > 1.0 \ or new_fit.components[-1].fwhm < 1.0/nbins: fit = False # Otherwise, keep fitting and update the parameters for the next pass else: fit = True prev_params = new_params prev_residuals = new_residuals prev_chi2 = new_chi2 prev_dof = new_dof # We stop when a fit is no longer needed, so we have to return the values # from the /previous/ run (otherwise we return the unneeded fit) #print "DEBUG: prev_params", prev_params finalfit = utils.multigaussfit_from_paramlist(prev_params) #print "DEBUG: finalfit", finalfit return finalfit