Source code for cifkit.coordination.method

from cifkit.utils.string_parser import get_atom_type_from_label


[docs] def compute_CN_max_gap_per_site( radius_sum_data, all_labels_connections, is_radius_data_available: bool, site_mixing_type: str, ) -> dict[str : dict[str : dict[str:float]]]: use_all_methods = False if is_radius_data_available and site_mixing_type == "full_occupancy": use_all_methods = True if use_all_methods: methods: dict[str, list[float]] = { "dist_by_shortest_dist": [], "dist_by_CIF_radius_sum": [], "dist_by_CIF_radius_refined_sum": [], "dist_by_Pauling_radius_sum": [], } else: methods = { "dist_by_shortest_dist": [], } norm_dists_per_label: dict = {} max_gaps_per_label: dict = {} for ref_label, connection_data in all_labels_connections.items(): # Initialize each label norm_dists_per_label[ref_label] = {key: [] for key in methods} max_gaps_per_label[ref_label] = { method: {"max_gap": 0, "CN": -1} for method in methods } # Limit to 20 connection data points connection_data = connection_data[:20] shortest_dist = connection_data[0][1] previous_values: dict[str, float] = {method: 0.0 for method in methods} for i, connection in enumerate(connection_data): pair_dist = connection[1] connected_label = connection[0] # Get new rad sum for each ref label if use_all_methods: CIF_radius_sum_norm_value = get_rad_sum_value( radius_sum_data, "CIF_radius_sum", ref_label, connected_label, ) CIF_radius_sum_refined_norm_value = get_rad_sum_value( radius_sum_data, "CIF_radius_refined_sum", ref_label, connected_label, ) Pauling_rad_sum_norm_value = get_rad_sum_value( radius_sum_data, "Pauling_radius_sum", ref_label, connected_label, ) norm_dist_by_CIF_radius_sum = compute_normalized_value( pair_dist, CIF_radius_sum_norm_value ) norm_dist_by_CIF_rad_ref_sum = compute_normalized_value( pair_dist, CIF_radius_sum_refined_norm_value ) norm_dist_by_Pauling_radius_sum = compute_normalized_value( pair_dist, Pauling_rad_sum_norm_value ) # Compute normalized distances norm_dist_by_min_dist = compute_normalized_value( pair_dist, shortest_dist ) # Store distances if use_all_methods: distances = { "dist_by_shortest_dist": norm_dist_by_min_dist, "dist_by_CIF_radius_sum": norm_dist_by_CIF_radius_sum, "dist_by_CIF_radius_refined_sum": norm_dist_by_CIF_rad_ref_sum, "dist_by_Pauling_radius_sum": norm_dist_by_Pauling_radius_sum, } else: distances = { "dist_by_shortest_dist": norm_dist_by_min_dist, } for method, norm_distance in distances.items(): norm_dists_per_label[ref_label][method].append(norm_distance) # Calculate and update max gaps if previous_values[method]: current_gap = round( abs(norm_distance - previous_values[method]), 3, ) if ( current_gap > max_gaps_per_label[ref_label][method]["max_gap"] ): max_gaps_per_label[ref_label][method][ "max_gap" ] = current_gap max_gaps_per_label[ref_label][method]["CN"] = i previous_values[method] = norm_distance return max_gaps_per_label
[docs] def compute_normalized_value(number: float, ref_number: float) -> float: return round((number / ref_number), 5)
[docs] def get_rad_sum_value( rad_sum_data, method_name: str, ref_label: str, other_label: str ) -> float: """Return the sum of radii value for a given pair of elements, ensuring the pair is alphabetically sorted.""" # Extract the element types from the labels ref_element = get_atom_type_from_label(ref_label) other_element = get_atom_type_from_label(other_label) # Sort the elements alphabetically to form a consistent key sorted_elements = sorted([ref_element, other_element]) key = f"{sorted_elements[0]}-{sorted_elements[1]}" # Ensure that method_name is valid and key exists in the dictionary if method_name not in rad_sum_data: raise KeyError(f"Method {method_name} not found in rad_sum") if key not in rad_sum_data[method_name]: raise KeyError( f"Key {key} not found in method {method_name} of rad_sum" ) return rad_sum_data[method_name][key]