Пример #1
0
    def calc_chi_sq(self, flag_internal: bool = True):
        """
        Calculate chi square.

        Keyword Arguments
        -----------------
            - flag_internal: a flag to calculate internal objects
              (default is True)

        Output arguments
        ----------------
            - chi_sq_val: chi square of flip ratio
              (Sum_i ((y_e_i - y_m_i) / sigma_i)**2)
            - n: number of measured reflections
        """
        self.apply_constraint()

        l_crystal = self.crystals()

        chi_sq_res, n_res = 0., 0.
        for experiment in self.experiments():
            chi_sq, n = experiment.calc_chi_sq(l_crystal,
                                               flag_internal=flag_internal)
            experiment.chi_sq = chi_sq
            experiment.n = n
            chi_sq_res += chi_sq
            n_res += n
            
        if flag_internal:
            refine_ls = RefineLs(goodness_of_fit_all= chi_sq_res/n_res,
                                 number_reflns=n_res)
            self.refine_ls = refine_ls

        return chi_sq_res, n_res
Пример #2
0
    def calc_chi_sq(
            self, l_crystal: List[Crystal], # or MagCrystal
            flag_internal=True, dict_in_out: dict = None):
        """
        Calculate chi square.

        Keyword Arguments
        -----------------
            - l_crystal: a list of Crystal objects of cryspy library
            - flag_internal: a flag to calculate internal objects
              (default is True)

        Output arguments
        ----------------
            - chi_sq_val: chi square of flip ratio
              (Sum_i ((y_e_i - y_m_i) / sigma_i)**2)
            - n: number of measured reflections
        """
        diffrn_refln = self.diffrn_refln
        index_h = diffrn_refln.numpy_index_h
        index_k = diffrn_refln.numpy_index_k
        index_l = diffrn_refln.numpy_index_l
        index_hkl = numpy.stack([index_h, index_k, index_l], axis=0)
        fr_exp = diffrn_refln.numpy_fr
        fr_sigma = diffrn_refln.numpy_fr_sigma
        fr_mod, dder = self.calc_iint_u_d_flip_ratio(index_hkl, l_crystal, flag_internal=flag_internal, dict_in_out=dict_in_out)

        if flag_internal:
            diffrn_refln.numpy_fr_calc = fr_mod
            # diffrn_refln.numpy_intensity_plus_calc = int_u_mod
            # diffrn_refln.numpy_intensity_minus_calc = int_d_mod
            diffrn_refln.numpy_to_items()

        flag_in = numpy.logical_not(diffrn_refln.numpy_excluded)

        chi_sq = ((fr_mod[flag_in]-fr_exp[flag_in])/fr_sigma[flag_in])**2
        chi_sq_val = (chi_sq[numpy.logical_not(numpy.isnan(chi_sq))]).sum()
        n = numpy.logical_not(numpy.isnan(chi_sq)).sum()

        if flag_internal:
            refine_ls = RefineLs(number_reflns=n,
                                 goodness_of_fit_all=chi_sq_val/float(n),
                                 weighting_scheme="sigma")
            self.refine_ls = refine_ls
        return chi_sq_val, n
Пример #3
0
def maximize_entropy(crystal: Crystal,
                     l_diffrn: List[Diffrn],
                     mem_parameters: MEMParameters,
                     c_lambda: float = 1e-7,
                     n_iterations: int = 10000,
                     disp: bool = True,
                     d_info: dict = None) -> DensityPointL:
    """
    Collins algroritm.

    Parameters
    ----------
    crystal : Crystal
        DESCRIPTION.
    l_diffrn : TYPE
        DESCRIPTION.
    c_lambda : float, optional
        DESCRIPTION. The default is 1e-7.
    n_iterations : int, optional
        DESCRIPTION. The default is 10000.
    chi_iso_ferro : float, optional
        DESCRIPTION. The default is 0..
    chi_iso_antiferro : float, optional
        DESCRIPTION. The default is 0..
    n_x : int, optional
        DESCRIPTION. The default is 48.
    n_y : int, optional
        DESCRIPTION. The default is 48.
    n_z : int, optional
        DESCRIPTION. The default is 48.
    prior_density: str, optional
        Choose of prior density: "core" or "uniform". The default is "uniform".
    flag_two_channel: bool, optional
        DESCRIPTION. The default is False.
    disp : bool, optional
        DESCRIPTION. The default is True.

    Returns
    -------
    DensityPointL
        Magnetization density.

    """
    flag_info = d_info is not None

    if flag_info:
        d_info_keys = d_info.keys()
        if "stop" not in d_info_keys:
            d_info["stop"] = False
        if "print" not in d_info_keys:
            d_info["print"] = ""

    chi_iso_ferro = mem_parameters.chi_ferro
    chi_iso_antiferro = mem_parameters.chi_antiferro
    points_a = mem_parameters.points_a
    points_b = mem_parameters.points_b
    points_c = mem_parameters.points_c
    prior_density = mem_parameters.prior_density
    flag_two_channel = mem_parameters.method == "2channel"
    gof_desired = mem_parameters.gof_desired

    cell = crystal.cell
    space_group = crystal.space_group
    atom_site = crystal.atom_site
    space_group_symop = space_group.full_space_group_symop
    if crystal.is_attribute("atom_site_susceptibility"):
        atom_site_susceptibility = crystal.atom_site_susceptibility
        l_magnetic_labes = atom_site_susceptibility.label
    else:
        atom_site_susceptibility = None
        l_magnetic_labes = []
    density_point = DensityPointL()
    if prior_density == "core":
        print("The prior density is core's one.", end="\r")
        if flag_info:
            d_info["print"] = "The prior density is core's one."

        atom_electron_configuration = crystal.atom_electron_configuration
        density_point.create_core_density(space_group_symop,
                                          cell,
                                          atom_site,
                                          atom_electron_configuration,
                                          points_a=points_a,
                                          points_b=points_b,
                                          points_c=points_c,
                                          flag_two_channel=flag_two_channel)
    else:
        print("The prior density is uniform.", end="\r")
        if flag_info:
            d_info["print"] = "The prior density is uniform."
        density_point.create_flat_density(space_group_symop,
                                          cell,
                                          atom_site,
                                          l_magnetic_labes=l_magnetic_labes,
                                          points_a=points_a,
                                          points_b=points_b,
                                          points_c=points_c,
                                          flag_two_channel=flag_two_channel)

    l_f_nucl, l_v_2d_i, l_fr_e, l_fr_s, l_fm_orb_perp_loc = [], [], [], [], []
    total_peaks = 0
    for diffrn in l_diffrn:
        diffrn_orient_matrix = diffrn.diffrn_orient_matrix
        u_matrix = diffrn_orient_matrix.u
        e_up = calc_e_up_loc(0., 0., 0., u_matrix)

        setup = diffrn.setup
        field = float(setup.field)
        h_loc = (field * e_up[0], field * e_up[1], field * e_up[2])
        diffrn_refln = diffrn.diffrn_refln
        ind_h = numpy.array(diffrn_refln.index_h, dtype=int)
        ind_k = numpy.array(diffrn_refln.index_k, dtype=int)
        ind_l = numpy.array(diffrn_refln.index_l, dtype=int)
        total_peaks += ind_h.size

        chi_m = crystal.calc_susceptibility_moment_tensor(
            ind_h, ind_k, ind_l, flag_only_orbital=True)
        sft_ij = chi_m[:9]
        sftm_ij = chi_m[9:]

        k_loc_i = cell.calc_k_loc(ind_h, ind_k, ind_l)
        fm_orb_perp_loc = calc_fm_perp_loc(e_up, field, k_loc_i, sft_ij,
                                           sftm_ij)

        hkl = (ind_h, ind_k, ind_l)
        fr_e = numpy.array(diffrn_refln.fr, dtype=float)
        fr_s = numpy.array(diffrn_refln.fr_sigma, dtype=float)
        v_hkl_perp_2d_i, v_b_ferro, v_b_antiferro = \
            density_point.calc_factor_in_front_of_density_for_fm_perp(
                hkl, space_group_symop, cell, atom_site_susceptibility, h_loc,
                chi_iso_ferro=chi_iso_ferro,
                chi_iso_antiferro=chi_iso_antiferro,
                flag_two_channel=flag_two_channel)
        f_nucl = crystal.calc_f_nucl(*hkl)
        l_f_nucl.append(f_nucl)
        l_v_2d_i.append((v_hkl_perp_2d_i, v_b_ferro, v_b_antiferro))
        l_fr_e.append(fr_e)
        l_fr_s.append(fr_s)
        l_fm_orb_perp_loc.append(fm_orb_perp_loc)

    def temp_func(numpy_den=None):
        l_chi_sq, l_der_chi_sq = [], []
        l_der_chi_sq_f, l_der_chi_sq_a = [], []
        for diffrn, f_nucl, v_2d_i, fr_e, fr_s, fm_orb_perp_loc in \
                zip(l_diffrn, l_f_nucl, l_v_2d_i, l_fr_e, l_fr_s,
                    l_fm_orb_perp_loc):
            diffrn_refln = diffrn.diffrn_refln

            f_m_perp, delta_f_m_perp, delta_f_m_perp_f, delta_f_m_perp_a = \
                density_point.calc_fm(*v_2d_i)

            # FIXME: put condition
            f_m_perp = (f_m_perp[0] + fm_orb_perp_loc[0],
                        f_m_perp[1] + fm_orb_perp_loc[1],
                        f_m_perp[2] + fm_orb_perp_loc[2])

            fr_m, delta_fr_m = diffrn.calc_fr(cell,
                                              f_nucl,
                                              f_m_perp,
                                              delta_f_nucl=None,
                                              delta_f_m_perp=delta_f_m_perp)
            delta_fr_m_f = diffrn.calc_fr(cell,
                                          f_nucl,
                                          f_m_perp,
                                          delta_f_nucl=None,
                                          delta_f_m_perp=delta_f_m_perp_f)[1]
            delta_fr_m_a = diffrn.calc_fr(cell,
                                          f_nucl,
                                          f_m_perp,
                                          delta_f_nucl=None,
                                          delta_f_m_perp=delta_f_m_perp_a)[1]

            diffrn_refln.numpy_fr_calc = fr_m
            chi_sq, der_chi_sq = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m)
            der_chi_sq_f = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m_f)[1]
            der_chi_sq_a = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m_a)[1]
            l_chi_sq.append(chi_sq)
            l_der_chi_sq.append(der_chi_sq)
            l_der_chi_sq_f.append(der_chi_sq_f)
            l_der_chi_sq_a.append(der_chi_sq_a)
        # print(" ".join([f" {val:10.2f}" for val in l_chi_sq]))
        return sum(l_chi_sq), sum(l_der_chi_sq), sum(l_der_chi_sq_f), \
            sum(l_der_chi_sq_a)

    chi_sq_best, chi_sq_n_diff = numpy.inf, numpy.inf
    numpy_density_best, numpy_density_ferro_best = None, None
    numpy_density_antiferro_best = None
    delta_chi_sq_best, delta_chi_sq_f_best = None, None
    delta_chi_sq_a_best = None

    mult_i = density_point.numpy_multiplicity

    c_lambda_min = 1e-9  # min value
    i_cycle = 0
    while i_cycle <= n_iterations:
        i_cycle += 1
        numpy_density = density_point.numpy_density
        numpy_density_ferro = density_point.numpy_density_ferro
        numpy_density_antiferro = density_point.numpy_density_antiferro
        chi_sq, delta_chi_sq, delta_chi_sq_f, delta_chi_sq_a = temp_func()

        chi_sq_n = chi_sq / float(total_peaks)
        if disp:
            print(f"cycle {i_cycle:5}. chi_sq/n: {chi_sq_n:.2f} \
{c_lambda*10**5:.3f} {chi_sq_n_diff:.4f}",
                  end="\r")
        if flag_info:
            d_info["print"] = f"""Iteration {i_cycle:5}:
    chi_sq/n: {chi_sq_n:.2f};
    c_lambda: {c_lambda*10**5:.3f} * 10**-5;
    difference of chi_sq/n: {chi_sq_n_diff:.4f}."""

        if chi_sq > chi_sq_best:
            numpy_density = numpy_density_best
            numpy_density_ferro = numpy_density_ferro_best
            numpy_density_antiferro = numpy_density_antiferro_best
            delta_chi_sq = delta_chi_sq_best
            delta_chi_sq_f = delta_chi_sq_f_best
            delta_chi_sq_a = delta_chi_sq_a_best
            c_lambda = 0.5 * c_lambda
        else:
            chi_sq_n_diff = (chi_sq_best - chi_sq) / float(total_peaks)
            chi_sq_best = chi_sq
            c_lambda = 1.03 * c_lambda

        if not (flag_two_channel):
            numpy_density_best = copy.deepcopy(numpy_density)
            delta_chi_sq_best = copy.deepcopy(delta_chi_sq)
        numpy_density_ferro_best = copy.deepcopy(numpy_density_ferro)
        numpy_density_antiferro_best = copy.deepcopy(numpy_density_antiferro)
        delta_chi_sq_f_best = copy.deepcopy(delta_chi_sq_f)
        delta_chi_sq_a_best = copy.deepcopy(delta_chi_sq_a)

        if chi_sq_n < gof_desired:
            print(f"OUT: cycle {i_cycle:5} chi_sq/n is less than \
{gof_desired:.2f}",
                  end="\r")
            if flag_info:
                d_info["print"] = f"""OUT on iteration {i_cycle:5}:
    chi_sq/n is less than {gof_desired:.2f}."""
            break
        elif ((c_lambda < c_lambda_min) & False):
            print(f"OUT: cycle {i_cycle:5} chi_sq/n is {chi_sq_n:.2f}. \
c_lambda: {c_lambda:}",
                  end="\r")
            if flag_info:
                d_info["print"] = f"""OUT on iteration {i_cycle:5}:
    chi_sq/n is {chi_sq_n:.2f}. c_lambda less minimal"""
            if not (flag_two_channel):
                density_point.numpy_density = numpy_density_best
            density_point.numpy_density_ferro = numpy_density_ferro_best
            density_point.numpy_density_antiferro = \
                numpy_density_antiferro_best
            density_point.renormalize_numpy_densities(
                flag_two_channel=flag_two_channel)
            break
        elif ((chi_sq_n_diff < 0.001) and (i_cycle > 10)):
            print(f"OUT: cycle {i_cycle:5} chi_sq/n is {chi_sq_n:.2f} as diff \
of GoF is less than 0.001.",
                  end="\r")
            if flag_info:
                d_info["print"] = f"""OUT on iteration {i_cycle:5}:
    chi_sq/n is {chi_sq_n:.2f};
    difference of GoF is less than 0.001."""
            break
        elif flag_info:
            if d_info["stop"]:
                d_info["stop"] = False
                break

        delta_chi_sq_f_mult_i = delta_chi_sq_f / mult_i
        delta_chi_sq_a_mult_i = delta_chi_sq_a / mult_i

        rel_diff = 0.05
        if not (flag_two_channel):
            delta_chi_sq_mult_i = delta_chi_sq / mult_i
            c_lambda = choose_max_clambda(c_lambda, numpy_density,
                                          delta_chi_sq_mult_i, rel_diff)
            density_point.numpy_density = numpy_density * numpy.exp(
                -c_lambda * delta_chi_sq_mult_i)
        else:
            c_lambda = choose_max_clambda(c_lambda, numpy_density_ferro,
                                          delta_chi_sq_f_mult_i, rel_diff)

        density_point.numpy_density_ferro = \
            numpy_density_ferro*numpy.exp(-c_lambda*delta_chi_sq_f_mult_i)
        density_point.numpy_density_antiferro = \
            numpy_density_antiferro*numpy.exp(-c_lambda*delta_chi_sq_a_mult_i)

        density_point.renormalize_numpy_densities(
            flag_two_channel=flag_two_channel)

    density_point.numpy_to_items()
    for diffrn in l_diffrn:
        diffrn.diffrn_refln.numpy_to_items()
        chi_sq, points = diffrn.diffrn_refln.calc_chi_sq_points()
        refine_ls = RefineLs(goodness_of_fit_all=chi_sq / points,
                             number_reflns=points)
        diffrn.add_items([refine_ls])
    return density_point
Пример #4
0
def refine_susceptibility(crystal: Crystal,
                          l_diffrn: List[Diffrn],
                          density_point: DensityPointL,
                          mem_parameters: MEMParameters,
                          disp: bool = True,
                          d_info: dict = None) -> (float, float):
    """
    Refinement of susceptibility.

    Parameters
    ----------
    crystal : Crystal
        DESCRIPTION.
    l_diffrn : TYPE
        DESCRIPTION.
    density_point : DensityPointL
        DESCRIPTION.
    chi_iso_ferro : float, optional
        DESCRIPTION. The default is 0..
    chi_iso_antiferro : float, optional
        DESCRIPTION. The default is 0..
    flag_ferro : bool, optional
        DESCRIPTION. The default is True.
    flag_antiferro : bool, optional
        DESCRIPTION. The default is True.
    disp : bool, optional
        DESCRIPTION. The default is True.

    Returns
    -------
    float
        Chi_iso_ferro.
    float
        Chi_iso_antiferro.

    """
    flag_info = d_info is not None

    if flag_info:
        d_info_keys = d_info.keys()
        if "stop" not in d_info_keys:
            d_info["stop"] = False
        if "print" not in d_info_keys:
            d_info["print"] = ""

    crystal.apply_constraints()

    flag_two_channel = mem_parameters.method == "2channel"

    cell = crystal.cell
    space_group = crystal.space_group
    atom_site = crystal.atom_site
    space_group_symop = space_group.full_space_group_symop
    atom_site_susceptibility = crystal.atom_site_susceptibility
    # l_magnetic_labes = atom_site_susceptibility.label

    volume = density_point.volume_unit_cell
    np = density_point.number_unit_cell

    den_i = density_point.numpy_density
    den_ferro_i = density_point.numpy_density_ferro
    den_antiferro_i = density_point.numpy_density_antiferro
    mult_i = density_point.numpy_multiplicity

    l_f_nucl, l_fr_e, l_fr_s, l_e_up, l_h_loc = [], [], [], [], []
    l_k_hkl, l_phase_3d = [], []
    l_chi_perp_ferro, l_chi_perp_antiferro = [], []
    total_peaks = 0
    for diffrn in l_diffrn:
        diffrn_orient_matrix = diffrn.diffrn_orient_matrix
        u_matrix = diffrn_orient_matrix.u
        e_up = calc_e_up_loc(0., 0., 0., u_matrix)

        setup = diffrn.setup
        field = float(setup.field)
        h_loc = (field * e_up[0], field * e_up[1], field * e_up[2])
        diffrn_refln = diffrn.diffrn_refln
        index_h = numpy.array(diffrn_refln.index_h, dtype=int)
        index_k = numpy.array(diffrn_refln.index_k, dtype=int)
        index_l = numpy.array(diffrn_refln.index_l, dtype=int)
        total_peaks += index_h.size
        hkl = (index_h, index_k, index_l)
        fr_e = numpy.array(diffrn_refln.fr, dtype=float)
        fr_s = numpy.array(diffrn_refln.fr_sigma, dtype=float)
        f_nucl = crystal.calc_f_nucl(*hkl)
        k_hkl = cell.calc_k_loc(*hkl)
        phase_3d = density_point.calc_phase_3d(hkl, space_group_symop)

        moment_2d, chi_2d_ferro, chi_2d_antiferro = \
            density_point.calc_moment_2d(
                space_group_symop, cell, atom_site_susceptibility, h_loc,
                chi_iso_ferro=1., chi_iso_antiferro=1.,
                flag_two_channel=flag_two_channel)

        chi_ferro = calc_fm_by_density(mult_i, den_ferro_i, np, volume,
                                       chi_2d_ferro, phase_3d)
        chi_perp_ferro = calc_moment_perp(k_hkl, chi_ferro)

        chi_aferro = calc_fm_by_density(mult_i, den_antiferro_i, np, volume,
                                        chi_2d_antiferro, phase_3d)
        chi_perp_aferro = calc_moment_perp(k_hkl, chi_aferro)

        l_f_nucl.append(f_nucl)
        l_fr_e.append(fr_e)
        l_fr_s.append(fr_s)
        l_e_up.append(e_up)
        l_h_loc.append(h_loc)
        l_k_hkl.append(k_hkl)
        l_phase_3d.append(phase_3d)
        l_chi_perp_ferro.append(chi_perp_ferro)
        l_chi_perp_antiferro.append(chi_perp_aferro)

    l_name_1 = atom_site_susceptibility.get_variable_names()
    l_par_1_0 = [
        atom_site_susceptibility.get_variable_by_name(name)
        for name in l_name_1
    ]

    l_name_2 = mem_parameters.get_variable_names()
    l_par_2_0 = [
        mem_parameters.get_variable_by_name(name) for name in l_name_2
    ]
    l_name = l_name_1 + l_name_2
    l_par_0 = l_par_1_0 + l_par_2_0

    def temp_func(l_par):
        for name, parameter in zip(l_name, l_par):
            if name[0][0] == "atom_site_susceptibility":
                atom_site_susceptibility.set_variable_by_name(name, parameter)
            elif name[0][0] == "mem_parameters":
                mem_parameters.set_variable_by_name(name, parameter)

        chi_iso_f = mem_parameters.chi_ferro
        chi_iso_af = mem_parameters.chi_antiferro

        atom_site_susceptibility.apply_chi_iso_constraint(cell)
        atom_site_susceptibility.apply_moment_iso_constraint(cell)
        atom_site_susceptibility.apply_space_group_constraint(
            atom_site, space_group)

        l_chi_sq = []
        l_der_chi_sq, l_der_chi_sq_f, l_der_chi_sq_a = [], [], []

        # FIXME: add flag for orbital magnetic moment
        for diffrn, f_nucl, fr_e, fr_s, e_up, h_loc, k_hkl, phase_3d, \
            chi_perp_ferro, chi_perp_aferro in \
            zip(l_diffrn, l_f_nucl, l_fr_e, l_fr_s, l_e_up, l_h_loc, l_k_hkl,
                l_phase_3d, l_chi_perp_ferro, l_chi_perp_antiferro):

            moment_2d, moment_ferro, moment_antiferro = \
                density_point.calc_moment_2d(
                    space_group_symop, cell, atom_site_susceptibility, h_loc,
                    chi_iso_ferro=1., chi_iso_antiferro=1.,
                    flag_two_channel=flag_two_channel)

            f_m = calc_fm_by_density(mult_i, den_i, np, volume, moment_2d,
                                     phase_3d)
            f_m_perp = calc_moment_perp(k_hkl, f_m)

            # # correction on orbital moment
            # diffrn_refln = diffrn.diffrn_refln
            # setup = diffrn.setup
            # field = setup.field
            # ind_h = diffrn_refln.numpy_index_h
            # ind_k = diffrn_refln.numpy_index_k
            # ind_l = diffrn_refln.numpy_index_l
            # chi_m = crystal.calc_susceptibility_moment_tensor(
            #     ind_h, ind_k, ind_l, flag_only_orbital=True)
            # sft_ij = chi_m[:9]
            # sftm_ij = chi_m[9:]

            # fm_orb_perp_loc = calc_fm_perp_loc(e_up, field, k_hkl, sft_ij,
            #                                    sftm_ij)

            # add ferro and anti_ferro

            f_m_perp_sum = (f_m_perp[0] + chi_iso_f * chi_perp_ferro[0] +
                            chi_iso_af * chi_perp_aferro[0],
                            f_m_perp[1] + chi_iso_f * chi_perp_ferro[1] +
                            chi_iso_af * chi_perp_aferro[1],
                            f_m_perp[2] + chi_iso_f * chi_perp_ferro[2] +
                            chi_iso_af * chi_perp_aferro[2])

            fr_m, delta_fr_m = diffrn.calc_fr(cell,
                                              f_nucl,
                                              f_m_perp_sum,
                                              delta_f_m_perp=f_m_perp)
            delta_fr_m_f = delta_fr_m
            delta_fr_m_a = delta_fr_m

            diffrn.diffrn_refln.numpy_fr_calc = fr_m

            chi_sq, der_chi_sq = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m)
            der_chi_sq_f = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m_f)[1]
            der_chi_sq_a = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m_a)[1]
            l_chi_sq.append(chi_sq)
            l_der_chi_sq.append(der_chi_sq)
            l_der_chi_sq_f.append(der_chi_sq_f)
            l_der_chi_sq_a.append(der_chi_sq_a)
        return sum(l_chi_sq)

    chi_sq = temp_func(l_par_0)
    print(f"Chi_sq before optimization {chi_sq/total_peaks:.5f}.           ",
          end="\r")
    if flag_info:
        d_info["print"] = \
            f"Chi_sq/n before optimization {chi_sq/total_peaks:.5f}."

    res = scipy.optimize.minimize(
        temp_func,
        l_par_0,
        method="BFGS",
        callback=lambda x: func_temp(x, param_name=l_name, d_info=d_info),
        options={"eps": 0.001})
    l_param = res.x
    chi_sq_new = res.fun

    hess_inv = res["hess_inv"]
    sigma = (abs(numpy.diag(hess_inv)))**0.5

    print(f"Chi_sq after optimization {chi_sq_new/total_peaks:.5f}.          ",
          end="\r")
    if flag_info:
        d_info["print"] = \
            f"Chi_sq/n after optimization {chi_sq_new/total_peaks:.5f}."

    for name, parameter, sig in zip(l_name, l_param, sigma):
        name_sig = name[:-1] + ((f"{name[-1][0]:}_sigma", name[-1][1]), )
        if name[0][0] == "atom_site_susceptibility":
            atom_site_susceptibility.set_variable_by_name(name, parameter)
            atom_site_susceptibility.set_variable_by_name(name_sig, sig)
        elif name[0][0] == "mem_parameters":
            mem_parameters.set_variable_by_name(name, parameter)
            mem_parameters.set_variable_by_name(name_sig, sig)

    for diffrn in l_diffrn:
        diffrn.diffrn_refln.numpy_to_items()
        chi_sq, points = diffrn.diffrn_refln.calc_chi_sq_points()
        refine_ls = RefineLs(goodness_of_fit_all=chi_sq / points,
                             number_reflns=points)
        diffrn.add_items([refine_ls])
Пример #5
0
    def calc_chi_sq(self, l_crystal, flag_internal: bool = True):
        """
        Calculate chi square.

        Arguments
        ---------
            - l_crystal: a list of Crystal objects of cryspy library
            - flag_internal: a flag to calculate internal objects
              (default is True)

        Output arguments
        ----------------
            - chi_sq_val: chi square of flip ratio
              (Sum_i ((y_e_i - y_m_i) / sigma_i)**2)
            - n: number of measured reflections
        """
        meas = self.pd2d_meas

        tth = meas.ttheta
        phi = meas.phi
        int_u_exp = meas.intensity_up
        sint_u_exp = meas.intensity_up_sigma
        int_d_exp = meas.intensity_down
        sint_d_exp = meas.intensity_down_sigma

        l_peak_in, l_refln_in = [], []
        l_refln_susceptibility_in = []
        l_dd_in = []
        flag_1 = not(flag_internal)

        try:
            dd = self.dd
            flag_2 = True
        except AttributeError:
            flag_2 = False
        if (flag_1 & flag_2):
            for phase_item in self.phase.items:
                crystal = None
                for cryst in l_crystal:
                    if cryst.data_name.lower() == phase_item.label.lower():
                        crystal = cryst
                        break
                attr_peak = f"pd2d_peak_{crystal.data_name:}"
                attr_refln = f"refln_{crystal.data_name:}"
                attr_refln_s = f"refln_susceptibility_{crystal.data_name:}"
                l_peak_in.append(getattr(self, attr_peak))
                l_refln_in.append(getattr(self, attr_refln))
                l_refln_susceptibility_in.append(getattr(self, attr_refln_s))

        cond_tth_in = numpy.ones(tth.size, dtype=bool)
        cond_phi_in = numpy.ones(phi.size, dtype=bool)
        try:
            range_ = self.range
            cond_tth_in = numpy.logical_and(cond_tth_in, tth >=
                                            range_.ttheta_min)
            cond_tth_in = numpy.logical_and(cond_tth_in, tth <=
                                            range_.ttheta_max)

            cond_phi_in = numpy.logical_and(cond_phi_in, phi >= range_.phi_min)
            cond_phi_in = numpy.logical_and(cond_phi_in, phi <= range_.phi_max)

        except AttributeError:
            pass
        # cond_1_in, cond_2_in = numpy.meshgrid(cond_tth_in, cond_phi_in,
        #                                       indexing="ij")
        # cond_in = numpy.logical_and(cond_1_in, cond_2_in)
        tth_in = tth[cond_tth_in]
        phi_in = phi[cond_phi_in]
        int_u_exp_in = int_u_exp[cond_tth_in, :][:, cond_phi_in]
        sint_u_exp_in = sint_u_exp[cond_tth_in, :][:, cond_phi_in]
        int_d_exp_in = int_d_exp[cond_tth_in, :][:, cond_phi_in]
        sint_d_exp_in = sint_d_exp[cond_tth_in, :][:, cond_phi_in]

        proc, l_peak, l_refln, l_dd_out = self.calc_profile(
            tth_in, phi_in, l_crystal, l_peak_in=l_peak_in,
            l_refln_in=l_refln_in,
            l_refln_susceptibility_in=l_refln_susceptibility_in,
            l_dd_in=l_dd_in, flag_internal=flag_internal)
        proc.intensity_up = int_u_exp_in
        proc.intensity_up_sigma = sint_u_exp_in
        proc.intensity_down = int_d_exp_in
        proc.intensity_down_sigma = sint_d_exp_in

        # self.proc = proc
        # self.peaks = l_peak
        # self.reflns = l_refln
        self.dd = l_dd_out

        int_u_mod = proc.intensity_up_total
        int_d_mod = proc.intensity_down_total

        sint_sum_exp_in = (sint_u_exp_in**2 + sint_d_exp_in**2)**0.5

        chi_sq_u = ((int_u_mod-int_u_exp_in)/sint_u_exp_in)**2
        chi_sq_d = ((int_d_mod-int_d_exp_in)/sint_d_exp_in)**2
        chi_sq_sum = ((int_u_mod+int_d_mod-int_u_exp_in-int_d_exp_in) /
                      sint_sum_exp_in)**2
        chi_sq_dif = ((int_u_mod-int_d_mod-int_u_exp_in+int_d_exp_in) /
                      sint_sum_exp_in)**2

        cond_u = numpy.logical_not(numpy.isnan(chi_sq_u))
        cond_d = numpy.logical_not(numpy.isnan(chi_sq_d))
        cond_sum = numpy.logical_not(numpy.isnan(chi_sq_sum))
        cond_dif = numpy.logical_not(numpy.isnan(chi_sq_dif))

        # exclude region
        try:
            exclude = self.exclude
            l_excl_tth_min = exclude.numpy_ttheta_min
            l_excl_tth_max = exclude.numpy_ttheta_max
            l_excl_phi_min = exclude.numpy_phi_min
            l_excl_phi_max = exclude.numpy_phi_max
            for excl_tth_min, excl_tth_max, excl_phi_min, excl_phi_max in \
                zip(l_excl_tth_min, l_excl_tth_max, l_excl_phi_min,
                    l_excl_phi_max):
                cond_1 = numpy.logical_or(tth_in < 1.*excl_tth_min,
                                          tth_in > 1.*excl_tth_max)
                cond_2 = numpy.logical_or(phi_in < 1.*excl_phi_min,
                                          phi_in > 1.*excl_phi_max)
                cond_11, cond_22 = numpy.meshgrid(cond_1, cond_2,
                                                  indexing="ij")
                cond_12 = numpy.logical_or(cond_11, cond_22)
                cond_u = numpy.logical_and(cond_u, cond_12)
                cond_d = numpy.logical_and(cond_d, cond_12)
                cond_sum = numpy.logical_and(cond_sum, cond_12)
        except AttributeError:
            pass

        chi_sq_u_val = (chi_sq_u[cond_u]).sum()
        n_u = cond_u.sum()

        chi_sq_d_val = (chi_sq_d[cond_d]).sum()
        n_d = cond_d.sum()

        chi_sq_sum_val = (chi_sq_sum[cond_sum]).sum()
        n_sum = cond_sum.sum()

        chi_sq_dif_val = (chi_sq_dif[cond_dif]).sum()
        n_dif = cond_dif.sum()
        chi2 = self.chi2
        flag_u = chi2.up
        flag_d = chi2.down
        flag_sum = chi2.sum
        flag_dif = chi2.diff

        chi_sq_val = (int(flag_u)*chi_sq_u_val + int(flag_d)*chi_sq_d_val +
                      int(flag_sum)*chi_sq_sum_val +
                      int(flag_dif)*chi_sq_dif_val)
        n = (int(flag_u)*n_u + int(flag_d)*n_d + int(flag_sum)*n_sum +
             int(flag_dif)*n_dif)
        # print(f"chi_sq_val/n: {chi_sq_val/n:.2f}    \
        #     chi_sq_val: {chi_sq_val: .2f}")
        # d_exp_out = {"chi_sq_val": chi_sq_val, "n": n}
        # d_exp_out.update(d_exp_prof_out)

        if flag_internal:
            refine_ls = RefineLs(number_reflns=n,
                                 goodness_of_fit_all=chi_sq_val/float(n),
                                 weighting_scheme="sigma")
            self.refine_ls = refine_ls
            proc.form_ttheta_phi_intensity_bkg_calc()
            proc.form_ttheta_phi_intensity_up()
            proc.form_ttheta_phi_intensity_up_sigma()
            proc.form_ttheta_phi_intensity_down()
            proc.form_ttheta_phi_intensity_down_sigma()
        return chi_sq_val, n
Пример #6
0
    def calc_chi_sq(self, l_crystal, flag_internal=True):
        """
        Calculate chi square.

        Arguments
        ---------
            - l_crystal: a list of Crystal objects of cryspy library
            - flag_internal: a flag to calculate or to use internal objects.
                   It should be True if user call the function.
                   It's True by default.

        Output
        ------
            - chi_sq_val: chi square of flip ratio
              (Sum_i ((y_e_i - y_m_i) / sigma_i)**2)
            - n: number of measured reflections
        """
        tof_meas = self.tof_meas
        flag_polarized = tof_meas.is_polarized()

        np_time = tof_meas.numpy_time
        if flag_polarized:
            int_u_exp = tof_meas.numpy_intensity_up
            sint_u_exp = tof_meas.numpy_intensity_up_sigma
            int_d_exp = tof_meas.numpy_intensity_down
            sint_d_exp = tof_meas.numpy_intensity_down_sigma
        else:
            int_exp = tof_meas.numpy_intensity
            sint_exp = tof_meas.numpy_intensity_sigma

        cond_in = numpy.ones(np_time.shape, dtype=bool)
        try:
            range_ = self.range
            time_min = numpy.array(range_.time_min, dtype=float)
            time_max = numpy.array(range_.time_max, dtype=float)

            cond_in = numpy.logical_and(cond_in, np_time >= time_min)
            cond_in = numpy.logical_and(cond_in, np_time <= time_max)
        except AttributeError:
            pass

        np_time_in = np_time[cond_in]
        if flag_polarized:
            int_u_exp_in = int_u_exp[cond_in]
            sint_u_exp_in = sint_u_exp[cond_in]
            int_d_exp_in = int_d_exp[cond_in]
            sint_d_exp_in = sint_d_exp[cond_in]
        else:
            int_exp_in = int_exp[cond_in]
            sint_exp_in = sint_exp[cond_in]

        tof_proc = self.calc_profile(
            np_time_in, l_crystal, flag_internal=flag_internal,
            flag_polarized=flag_polarized)

        if flag_polarized:
            tof_proc.numpy_intensity_up = int_u_exp_in
            tof_proc.numpy_intensity_up_sigma = sint_u_exp_in
            tof_proc.numpy_intensity_down = int_d_exp_in
            tof_proc.numpy_intensity_down_sigma = sint_d_exp_in
            tof_proc.numpy_intensity = int_u_exp_in+int_d_exp_in
            tof_proc.numpy_intensity_sigma = numpy.sqrt(
                numpy.square(sint_u_exp_in) + numpy.square(sint_d_exp_in))
        else:
            tof_proc.numpy_intensity = int_exp_in
            tof_proc.numpy_intensity_sigma = sint_exp_in

        int_u_mod = tof_proc.numpy_intensity_up_total
        int_d_mod = tof_proc.numpy_intensity_down_total

        if flag_polarized:
            sint_sum_exp_in = (sint_u_exp_in**2 + sint_d_exp_in**2)**0.5
            chi_sq_u = ((int_u_mod-int_u_exp_in)/sint_u_exp_in)**2
            chi_sq_d = ((int_d_mod-int_d_exp_in)/sint_d_exp_in)**2
            chi_sq_sum = ((int_u_mod+int_d_mod-int_u_exp_in-int_d_exp_in) /
                          sint_sum_exp_in)**2
            chi_sq_dif = ((int_u_mod-int_d_mod-int_u_exp_in+int_d_exp_in) /
                          sint_sum_exp_in)**2

            cond_u = numpy.logical_not(numpy.isnan(chi_sq_u))
            cond_d = numpy.logical_not(numpy.isnan(chi_sq_d))
            cond_sum = numpy.logical_not(numpy.isnan(chi_sq_sum))
            cond_dif = numpy.logical_not(numpy.isnan(chi_sq_dif))
        else:
            chi_sq_sum = ((int_u_mod+int_d_mod-int_exp_in)/sint_exp_in)**2
            cond_sum = numpy.logical_not(numpy.isnan(chi_sq_sum))

        # exclude region
        try:
            exclude = self.exclude
            l_excl_time_min = exclude.time_low
            l_excl_time_max = exclude.time_high
            if flag_polarized:
                for excl_time_min, excl_time_max in zip(l_excl_time_min,
                                                        l_excl_time_max):
                    cond_1 = numpy.logical_or(np_time_in < 1.*excl_time_min,
                                              np_time_in > 1.*excl_time_max)
                    cond_u = numpy.logical_and(cond_u, cond_1)
                    cond_d = numpy.logical_and(cond_d, cond_1)
                    cond_sum = numpy.logical_and(cond_sum, cond_1)
            else:
                for excl_time_min, excl_time_max in zip(l_excl_time_min,
                                                        l_excl_time_max):
                    cond_1 = numpy.logical_or(np_time_in < 1.*excl_time_min,
                                              np_time_in > 1.*excl_time_max)
                    cond_sum = numpy.logical_and(cond_sum, cond_1)
        except AttributeError:
            pass

        tof_proc.numpy_excluded = numpy.logical_not(cond_sum)
        chi_sq_sum_val = (chi_sq_sum[cond_sum]).sum()
        n_sum = cond_sum.sum()

        if flag_polarized:

            chi_sq_u_val = (chi_sq_u[cond_u]).sum()
            n_u = cond_u.sum()

            chi_sq_d_val = (chi_sq_d[cond_d]).sum()
            n_d = cond_d.sum()

            chi_sq_dif_val = (chi_sq_dif[cond_dif]).sum()
            n_dif = cond_dif.sum()

            chi2 = self.chi2

            flag_u = chi2.up
            flag_d = chi2.down
            flag_sum = chi2.sum
            flag_dif = chi2.diff

            chi_sq_val = (int(flag_u)*chi_sq_u_val + int(flag_d)*chi_sq_d_val +
                          int(flag_sum)*chi_sq_sum_val +
                          int(flag_dif)*chi_sq_dif_val)
            n = (int(flag_u)*n_u + int(flag_d)*n_d + int(flag_sum)*n_sum +
                 int(flag_dif)*n_dif)
        else:
            chi_sq_val = chi_sq_sum_val
            n = n_sum

        if flag_internal:
            refine_ls = RefineLs(number_reflns=n,
                                 goodness_of_fit_all=chi_sq_val/float(n),
                                 weighting_scheme="sigma")
            self.refine_ls = refine_ls
            tof_proc.numpy_to_items()
        return chi_sq_val, n
Пример #7
0
    def calc_fr(self):
        """Calculate Flip Ratios for diffraction experiments."""
        crystal = self.crystals()[0]  # FIXME:
        l_diffrn = self.experiments()  # FIXME:
        density_point = self.density_point
        mem_parameters = self.mem_parameters
        chi_iso_ferro = mem_parameters.chi_ferro
        chi_iso_antiferro = mem_parameters.chi_antiferro

        flag_two_channel = mem_parameters.method == "2channel"

        cell = crystal.cell
        space_group = crystal.space_group
        space_group_symop = space_group.full_space_group_symop
        atom_site_susceptibility = crystal.atom_site_susceptibility

        # FIXME: temporary solution of calculation rbs_i if it's not defined
        density_point.calc_rbs_i(space_group_symop,
                                 points_a=mem_parameters.points_a,
                                 points_b=mem_parameters.points_b,
                                 points_c=mem_parameters.points_c)

        total_peaks = 0

        den_i = numpy.array(density_point.density, dtype=float)
        den_ferro_i = numpy.array(density_point.density_ferro, dtype=float)
        den_antiferro_i = numpy.array(density_point.density_antiferro,
                                      dtype=float)
        mult_i = numpy.array(density_point.multiplicity, dtype=int)

        volume = cell.volume
        n_points = mult_i.sum()

        for diffrn in l_diffrn:
            diffrn_orient_matrix = diffrn.diffrn_orient_matrix
            e_up = diffrn_orient_matrix.calc_e_up()
            setup = diffrn.setup
            field = float(setup.field)
            h_loc = (field * e_up[0], field * e_up[1], field * e_up[2])
            diffrn_refln = diffrn.diffrn_refln
            index_h = numpy.array(diffrn_refln.index_h, dtype=int)
            index_k = numpy.array(diffrn_refln.index_k, dtype=int)
            index_l = numpy.array(diffrn_refln.index_l, dtype=int)
            total_peaks += index_h.size
            hkl = (index_h, index_k, index_l)

            f_nucl = crystal.calc_f_nucl(*hkl)
            k_hkl = cell.calc_k_loc(*hkl)
            phase_3d = density_point.calc_phase_3d(hkl, space_group_symop)

            moment_2d, chi_2d_ferro, chi_2d_antiferro = \
                density_point.calc_moment_2d(
                    space_group_symop, cell, atom_site_susceptibility, h_loc,
                    chi_iso_ferro=1., chi_iso_antiferro=1.,
                    flag_two_channel=flag_two_channel)

            chi_ferro = calc_fm_by_density(mult_i, den_ferro_i, n_points,
                                           volume, chi_2d_ferro, phase_3d)
            chi_perp_ferro = calc_moment_perp(k_hkl, chi_ferro)

            chi_aferro = calc_fm_by_density(mult_i, den_antiferro_i, n_points,
                                            volume, chi_2d_antiferro, phase_3d)
            chi_perp_aferro = calc_moment_perp(k_hkl, chi_aferro)

            f_m = calc_fm_by_density(mult_i, den_i, n_points, volume,
                                     moment_2d, phase_3d)
            f_m_perp = calc_moment_perp(k_hkl, f_m)

            f_m_perp_sum = (f_m_perp[0] + chi_iso_ferro * chi_perp_ferro[0] +
                            chi_iso_antiferro * chi_perp_aferro[0],
                            f_m_perp[1] + chi_iso_ferro * chi_perp_ferro[1] +
                            chi_iso_antiferro * chi_perp_aferro[1],
                            f_m_perp[2] + chi_iso_ferro * chi_perp_ferro[2] +
                            chi_iso_antiferro * chi_perp_aferro[2])

            fr_m, delta_fr_m = diffrn.calc_fr(cell,
                                              f_nucl,
                                              f_m_perp_sum,
                                              delta_f_m_perp=f_m_perp)
            diffrn.diffrn_refln.numpy_fr_calc = fr_m
        for diffrn in l_diffrn:
            diffrn.diffrn_refln.numpy_to_items()
            chi_sq, points = diffrn.diffrn_refln.calc_chi_sq_points()
            refine_ls = RefineLs(goodness_of_fit_all=chi_sq / points,
                                 number_reflns=points)
            diffrn.add_items([refine_ls])