Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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 
Esempio n. 4
0
 def func(params):
     #print "DEBUG: params", params
     fit = utils.multigaussfit_from_paramlist(params)
     return fit.get_resids(data)
Esempio n. 5
0
 def func(params, fjac=None, errs=None):
     fit = utils.multigaussfit_from_paramlist(params)
     # Return values are [status, residuals]
     return [0, fit.get_resids(data)]
Esempio n. 6
0
 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)
Esempio n. 7
0
    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
Esempio n. 8
0
 def func(params):
     #print "DEBUG: params", params
     fit = utils.multigaussfit_from_paramlist(params)
     return fit.get_resids(data)
Esempio n. 9
0
 def func(params, fjac=None, errs=None):
     fit = utils.multigaussfit_from_paramlist(params)
     # Return values are [status, residuals]
     return [0, fit.get_resids(data)]
Esempio n. 10
0
 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)