Beispiel #1
0
    def getDerivative(self):
        deriv = []

        for index in range(self.diffraction_patterns_number):
            twotheta_experimental = self.twotheta_experimental_list[index]
            error_experimental = self.error_experimental_list[index]

            y = fit_function_direct(twotheta_experimental,
                                    self.build_fit_global_parameters_out(
                                        self.parameters),
                                    diffraction_pattern_index=index)

            nr_points_i = self.getNrPoints(index)
            deriv_i = CMatrix(self.getNrParamToFit(), nr_points_i)

            jj = 0
            for k in range(0, self.nprm):
                parameter = self.parameters[k]

                if parameter.is_variable():
                    pk = parameter.value
                    if parameter.step == PARAM_ERR: step = 0.001
                    else: step = parameter.step

                    if abs(pk) > PRCSN:
                        d = pk * step
                        parameter.value = pk * (1.0 + step)
                        parameter.check_value()

                        deriv_i[jj] = fit_function_direct(
                            twotheta_experimental,
                            self.build_fit_global_parameters_out(
                                self.parameters),
                            diffraction_pattern_index=index)
                    else:
                        d = step
                        parameter.value = pk + d
                        parameter.check_value()

                        deriv_i[jj] = fit_function_direct(
                            twotheta_experimental,
                            self.build_fit_global_parameters_out(
                                self.parameters),
                            diffraction_pattern_index=index)

                    parameter.value = pk
                    parameter.check_value()

                    for i in range(0, nr_points_i):
                        if error_experimental[i] == 0:
                            deriv_i[jj][i] = 0.0
                        else:
                            deriv_i[jj][i] = (deriv_i[jj][i] - y[i]) / (
                                d * error_experimental[i])
                    jj += 1

            deriv.append(deriv_i)

        return deriv
Beispiel #2
0
    def getWeightedDelta(self):
        fmm = []

        for index in range(self.diffraction_patterns_number):
            twotheta_experimental = self.twotheta_experimental_list[index]
            intensity_experimental = self.intensity_experimental_list[index]
            error_experimental = self.error_experimental_list[index]

            y = fit_function_direct(twotheta_experimental,
                                    self.build_fit_global_parameters_out(
                                        self.parameters),
                                    diffraction_pattern_index=index)

            fmm_i = [0] * self.getNrPoints(index)

            for i in range(0, self.getNrPoints(index)):
                if error_experimental[i] == 0:
                    fmm_i[i] = 0
                else:
                    fmm_i[i] = (y[i] - intensity_experimental[i]
                                ) / error_experimental[i]

            fmm.append(fmm_i)

        return fmm
Beispiel #3
0
    def build_fitted_diffraction_pattern(self, fit_global_parameters):

        fitted_patterns = []

        for index in range(
                len(fit_global_parameters.fit_initialization.
                    diffraction_patterns)):
            wavelength = fit_global_parameters.fit_initialization.diffraction_patterns[
                index].wavelength

            fitted_pattern = DiffractionPattern(wavelength=wavelength)

            fitted_intensity = fit_function_direct(
                self.twotheta_experimental_list[index],
                fit_global_parameters,
                diffraction_pattern_index=index)
            fitted_residual = self.intensity_experimental_list[
                index] - fitted_intensity

            for i in range(0, len(fitted_intensity)):
                fitted_pattern.add_diffraction_point(
                    diffraction_point=DiffractionPoint(
                        twotheta=self.twotheta_experimental_list[index][i],
                        intensity=fitted_intensity[i],
                        error=fitted_residual[i]))
            fitted_patterns.append(fitted_pattern)

        return fitted_patterns
Beispiel #4
0
    def getSSQFromData(self, y_list=None):
        if y_list is None:
            y_list = [None] * self.diffraction_patterns_number

            for index in range(self.diffraction_patterns_number):
                y_list[index] = fit_function_direct(
                    self.twotheta_experimental_list[index],
                    self.build_fit_global_parameters_out(self.parameters),
                    index)

        ss = 0.0

        for index in range(self.diffraction_patterns_number):
            y = y_list[index]
            intensity_experimental = self.intensity_experimental_list[index]

            for i in range(0, self.getNrPoints(index)):
                if self.mighell:
                    yv = y[i] - (intensity_experimental[i] +
                                 (intensity_experimental[i]
                                  if intensity_experimental[i] < 1 else 1.0))
                else:
                    yv = (y[i] - intensity_experimental[i])

                ss += yv**2

        return ss
Beispiel #5
0
    def getWSQFromData(self, y_list=None):
        if y_list is None:
            y_list = [None] * self.diffraction_patterns_number

            for index in range(self.diffraction_patterns_number):
                y_list[index] = fit_function_direct(
                    self.twotheta_experimental_list[index],
                    self.build_fit_global_parameters_out(self.parameters),
                    index)

        wssq = 0.0

        for index in range(self.diffraction_patterns_number):
            y = y_list[index]
            intensity_experimental = self.intensity_experimental_list[index]
            error_experimental = self.error_experimental_list[index]

            for i in range(0, self.getNrPoints(index)):
                if not self.mighell:
                    if error_experimental[i] == 0.0:
                        yv = 0.0
                    else:
                        yv = (y[i] - intensity_experimental[i]
                              ) / error_experimental[i]

                    wssq += (yv**2)
                else:
                    if intensity_experimental[i] < 1:
                        yv = y[i] - 2 * intensity_experimental[i]
                    else:
                        yv = y[i] - (intensity_experimental[i] + 1.0)

                    wssq += (yv**2) / (error_experimental[i]**2 + 1.0)

        return wssq
Beispiel #6
0
    def getWSSQ(self, y_list=None):
        if y_list is None:
            y_list = [None] * self.diffraction_patterns_number

            for index in range(self.diffraction_patterns_number):
                y_list[index] = fit_function_direct(
                    self.twotheta_experimental_list[index],
                    self.build_fit_global_parameters_out(self.parameters),
                    index)

        wssqlow = 0.0
        wssq = 0.0

        for index in range(self.diffraction_patterns_number):
            y = y_list[index]
            intensity_experimental = self.intensity_experimental_list[index]
            error_experimental = self.error_experimental_list[index]

            if self.mighell:
                for i in range(0, self.getNrPoints(index)):
                    yv = y[i] - (intensity_experimental[i] +
                                 (intensity_experimental[i]
                                  if intensity_experimental[i] < 1 else 1.0))

                    wssqtmp = (yv**2) / (error_experimental[i]**2 + 1.0)

                    if (wssqtmp < 1E-2):
                        wssqlow += wssqtmp
                    else:
                        wssq += wssqtmp
            else:
                for i in range(0, self.getNrPoints(index)):
                    if error_experimental[i] == 0.0:
                        yv = 0.0
                    else:
                        yv = (y[i] - intensity_experimental[i]
                              ) / error_experimental[i]

                    wssqtmp = (yv**2)

                    if (wssqtmp < 1E-2):
                        wssqlow += wssqtmp
                    else:
                        wssq += wssqtmp

        return wssq + wssqlow
Beispiel #7
0
    def do_fit(self, current_fit_global_parameters, current_iteration):
        print("Fitter - Begin iteration nr. " + str(current_iteration))

        self.fit_global_parameters = current_fit_global_parameters.duplicate()

        if current_iteration <= current_fit_global_parameters.get_n_max_iterations(
        ) and not self.conver:
            # check values of lambda for large number of iterations
            if (self._totIter > 4 and self._lambda < self._lmin):
                self._lmin = self._lambda

            #update total number of iterations
            self._totIter += 1

            #decrease lambda using golden section 0.31622777=1/(sqrt(10.0))
            self._lambda *= 0.31622777

            #number of increments in lambda
            self._nincr = 0

            #zero the working arrays
            self.a.zero()
            self.grad.zero()

            self.set()

            self.c.assign(
                self.a
            )  #save the matrix A and the current value of the parameters

            j = 0
            for i in range(0, self.nprm):
                if self.parameters[i].is_variable():
                    j += 1
                    self.initialpar.setitem(j, self.parameters[i].value)
                    self.currpar.setitem(j, self.initialpar.getitem(j))

            # emulate C++ do ... while cycle
            do_cycle = True

            print("Begin Minization using LAMBDA: ", self._lambda)

            while do_cycle:
                self.exitflag = False
                self.conver = False

                #set the diagonal of A to be A*(1+lambda)+phi*lambda
                da = self._phi * self._lambda

                for jj in range(1, self.nfit + 1):
                    self.g.setitem(jj, -self.grad.getitem(jj))
                    l = int(jj * (jj + 1) / 2)
                    self.a.setitem(
                        l,
                        self.c.getitem(l) * (1.0 + self._lambda) + da)
                    if jj > 1:
                        for i in range(1, jj):
                            self.a.setitem(l - i, self.c.getitem(l - i))

                if self.a.chodec() == 0:  # Cholesky decomposition
                    # the matrix is inverted, so calculate g (change in the
                    # parameters) by back substitution

                    self.a.choback(self.g)

                    prevwss = self.oldwss
                    recycle = 1

                    # Update the parameters: param = old param + g
                    # n0 counts the number of zero elements in g
                    do_cycle_2 = True
                    while do_cycle_2:
                        recyc = False
                        n0 = 0
                        i = 0
                        for j in range(0, self.nprm):
                            if self.parameters[j].is_variable():
                                i += 1

                                # update value of parameter
                                #  apply the required constraints (min/max)
                                self.parameters[j].set_value(
                                    self.currpar.getitem(i) +
                                    recycle * self.g.getitem(i))

                                # check number of parameters reaching convergence
                                if (abs(self.g.getitem(i)) <= abs(
                                        PRCSN * self.currpar.getitem(i))):
                                    n0 += 1

                        # calculate functions

                        #self.parameters = self.build_fit_global_parameters_out(self.parameters).get_parameters()
                        FitGlobalParameters.compute_functions(
                            self.parameters, current_fit_global_parameters.
                            free_input_parameters,
                            current_fit_global_parameters.
                            free_output_parameters)

                        if (n0 == self.nfit):
                            self.conver = True

                        # update the wss
                        self.wss = self.getWSSQ()

                        if self.wss < prevwss:
                            prevwss = self.wss
                            recyc = True
                            recycle += 1

                        # last line of while loop
                        do_cycle_2 = recyc and recycle < 10

                    if recycle > 1:

                        # restore parameters to best value
                        recycle -= 1

                        i = 0
                        for j in range(0, self.nprm):
                            if self.parameters[j].is_variable():
                                i += 1

                                # update value of parameter
                                #  apply the required constraints (min/max)
                                self.parameters[j].set_value(
                                    self.currpar.getitem(i) +
                                    recycle * self.g.getitem(i))

                        # calculate functions
                        #self.parameters = self.build_fit_global_parameters_out(self.parameters).get_parameters()
                        FitGlobalParameters.compute_functions(
                            self.parameters, current_fit_global_parameters.
                            free_input_parameters,
                            current_fit_global_parameters.
                            free_output_parameters)

                        # update the wss
                        self.wss = self.getWSSQ()

                    # if all parameters reached convergence then it's time to quit

                    if self.wss < self.oldwss:
                        self.oldwss = self.wss
                        self.exitflag = True

                        ii = 0
                        for j in range(0, self.nprm):
                            if self.parameters[j].is_variable():
                                ii += 1

                                # update value of parameter
                                self.initialpar.setitem(
                                    ii,
                                    self.currpar.getitem(ii) +
                                    recycle * self.g.getitem(ii))

                    y_list = [None] * self.diffraction_patterns_number

                    for index in range(self.diffraction_patterns_number):
                        y_list[index] = fit_function_direct(
                            self.twotheta_experimental_list[index],
                            self.build_fit_global_parameters_out(
                                self.parameters), index)

                    self.build_minpack_data(y_list=y_list)

                    print(self.fit_data.to_text())
                else:
                    #self.parameters = self.build_fit_global_parameters_out(self.parameters).get_parameters()
                    FitGlobalParameters.compute_functions(
                        self.parameters,
                        current_fit_global_parameters.free_input_parameters,
                        current_fit_global_parameters.free_output_parameters)

                    print("Chlolesky decomposition failed!")

                if not self.exitflag and not self.conver:
                    if self._lambda < PRCSN: self._lambda = PRCSN
                    self._nincr += 1
                    self._lambda *= 10.0
                    if self._lambda > (1E5 * self._lmin): self.conver = True

                # last line of the while loop
                do_cycle = not self.exitflag and not self.conver

            j = 0
            for i in range(0, self.nprm):
                if self.parameters[i].is_variable():
                    j += 1
                    self.parameters[i].set_value(self.initialpar.getitem(j))

            #self.parameters = self.build_fit_global_parameters_out(self.parameters).get_parameters()
            FitGlobalParameters.compute_functions(
                self.parameters,
                current_fit_global_parameters.free_input_parameters,
                current_fit_global_parameters.free_output_parameters)

        fitted_parameters = self.parameters

        fit_global_parameters_out = self.build_fit_global_parameters_out(
            fitted_parameters)
        fit_global_parameters_out.set_convergence_reached(self.conver)

        fitted_patterns = self.build_fitted_diffraction_pattern(
            fit_global_parameters=fit_global_parameters_out)

        self.conver = False

        errors = [0] * len(self.parameters)

        self.a.zero()
        self.grad.zero()
        self.set()

        if self.a.chodec() == 0:  # Cholesky decomposition
            k = 0
            for i in range(0, self.nprm):
                if self.parameters[i].is_variable():

                    self.g.zero()
                    self.g[k] = 1.0
                    self.a.choback(self.g)
                    errors[i] = numpy.sqrt(numpy.abs(self.g[k]))
                    k += 1
        else:
            print("Errors not calculated: chodec != 0")

        fit_global_parameters_out = self.build_fit_global_parameters_out_errors(
            errors=errors)

        return fitted_patterns, fit_global_parameters_out, self.fit_data