Exemplo n.º 1
0
def test_chichi():
    magic_residuals = mock.MagicMock()

    parameters = []
    magic_residuals.residuals_fn.return_value = np.array([0, 1, 50])

    parameters2 = [0, 6, 5]
    chichi = microltoolbox.chichi(magic_residuals.residuals_fn, parameters2)

    assert chichi == 2501
Exemplo n.º 2
0
    def lmarquardt(self):
        """The LM method. This is based on the Levenberg-Marquardt algorithm:

           "A Method for the Solution of Certain Problems in Least Squares"
           Levenberg, K. Quart. Appl. Math. 2, 1944, p. 164-168
           "An Algorithm for Least-Squares Estimation of Nonlinear Parameters"
           Marquardt, D. SIAM J. Appl. Math. 11, 1963, p. 431-441

           Based on scipy.optimize.leastsq python routine, which is based on MINPACK's lmdif and
           lmder
           algorithms (fortran based).

           The objective function is :func:`residuals_LM`.
           The starting point parameters are self.guess.
           the Jacobian is given by :func:`LM_Jacobian`.

           The fit is performed on all parameters : Paczynski parameters and telescopes fluxes.

           :return: a tuple containing (fit_results, covariance_matrix, computation_time)
           :rtype: tuple

           **WARNING**:
                     ftol (relative error desired in the sum of square) is set to 10^-6
                     maxfev (maximum number of function call) is set to 50000
                     These limits can avoid the fit to properly converge (expected to be rare :))
        """
        starting_time = python_time.time()

        # use the analytical Jacobian (faster) if no second order are present, else let the
        # algorithm find it.
        if self.guess == []:
            self.guess = self.initial_guess()

        if self.model.Jacobian_flag == 'OK':
            lmarquardt_fit = scipy.optimize.leastsq(self.residuals_LM,
                                                    self.guess,
                                                    maxfev=50000,
                                                    Dfun=self.LM_Jacobian,
                                                    col_deriv=0,
                                                    full_output=1,
                                                    ftol=10**-6,
                                                    xtol=10**-10,
                                                    gtol=10**-5)
        else:

            lmarquardt_fit = scipy.optimize.leastsq(self.residuals_LM,
                                                    self.guess,
                                                    maxfev=50000,
                                                    full_output=1,
                                                    ftol=10**-6,
                                                    xtol=10**-10,
                                                    gtol=10**-5,
                                                    factor=0.1)
        # import pdb;
        # pdb.set_trace()
        computation_time = python_time.time() - starting_time

        fit_result = lmarquardt_fit[0].tolist()
        fit_result.append(
            microltoolbox.chichi(self.residuals_LM, lmarquardt_fit[0]))

        n_data = 0.0

        for telescope in self.event.telescopes:
            n_data = n_data + telescope.n_data('flux')

        n_parameters = len(self.model.model_dictionnary)

        try:
            # Try to extract the covariance matrix from the lmarquard_fit output

            if np.all(lmarquardt_fit[1].diagonal() > 0) & (lmarquardt_fit[1]
                                                           is not None):
                # Normalise the output by the reduced chichi
                covariance_matrix = lmarquardt_fit[1] * fit_result[-1] / (
                    n_data - n_parameters)

            # Try to do it "manually"
            else:

                print(' Attempt to construct a rough covariance matrix')
                jacobian = self.LM_Jacobian(fit_result)

                covariance_matrix = np.linalg.inv(np.dot(jacobian.T, jacobian))
                # Normalise the output by the reduced chichi
                covariance_matrix = covariance_matrix * fit_result[-1] / (
                    n_data - n_parameters)

                # Construct a dummy covariance matrix
                if np.any(lmarquardt_fit[1].diagonal() > 0):
                    print('Bad covariance covariance matrix')
                    covariance_matrix = np.zeros(
                        (len(self.model.model_dictionnary),
                         len(self.model.model_dictionnary)))

        # Construct a dummy covariance matrix
        except:
            print('Bad covariance covariance matrix')
            covariance_matrix = np.zeros((len(self.model.model_dictionnary),
                                          len(self.model.model_dictionnary)))

        # import pdb; pdb.set_trace()
        print(sys._getframe().f_code.co_name,
              ' : Levenberg_marquardt fit SUCCESS')
        print(fit_result)
        return fit_result, covariance_matrix, computation_time