Project: s41467-024-49163-7 | Function: calc_female_fertilization_weights (python)

system: You are an expert Python programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow Python best practices and maintain consistent code style.
Return **only** the complete Python function code.

user: Complete this Python function:

**DESCRIPTION:** Implements the fitness weighting algorithm based on fertilization probabilities of diploid maternal plants. Calculates weights using the paper's fitness function W_i = 1 - (1-y_g)^k where y_g is the proportion of compatible pollen.

**KEY TERMS:** {
  "diploid_count_dict": "diploid maternal genotypes g",
  "haplotypes_count_dict": "haplotype frequencies x_h",
  "delta_g_r_dict": "compatibility relations Δ_g←h^H",
  "p_fertilize_haps": "compatible pollen proportion y_g",
  "Wi": "maternal plant fitness W_g"
}

**CONTEXT CODE:**         for k in range(Model.slf_amount_in_haploid):
            haplotype.SLFsIndices.append(haplotype.Male_part[k].IndexInSLFsPool)
        haplotype.PreviousHaplotype = []
        haplotype.BirthIter = 0
        haplotype.BirthReason = 'Initiation'
        haplotype.RNases_len = len(haplotype.RNasesIndices)
        haplotype.SLFs_unique_len = len(np.unique(haplotype.SLFsIndices))
        haplotype.SLFs_len = len(haplotype.SLFsIndices)
        haplotype.SLFsIndices_unique = np.unique(haplotype.SLFsIndices)
        haplotype.RNasesAncestralIndices = haplotype.RNasesIndices
        haplotype.SLFsAncestralIndices = haplotype.SLFsIndices
        haplotypes_dict[ind] = haplotype

    return haplotypes_dict


def is_compatible(E_Ri_Fj_dict, unique_SLFs_indices, unique_RNases_indices):
    # at least one of the SLFs can detoxify the RNase
    is_compatible = False
    for ii_slfs, slf_ind in enumerate(unique_SLFs_indices):
        if E_Ri_Fj_dict[int(unique_RNases_indices),slf_ind] < Model.interaction_thresh:
            is_compatible = True
            break

    return is_compatible

# -----------------------------------------------------------
#         CALCULATE INTERACTIONS
# -----------------------------------------------------------

def Calc_Interaction_Energy(female_al_pool, male_al_pool, eij, seq_len):
    '''
    this function calculates the interaction intensities between all the pairs of alleles in the pool.
    the Interaction between the two alleles is calculated by summing the interaction correspondences along the pair of alleles (i and j)
    The total interaction energy - equals the sum of interactions between the corresponding amino acids of the two protein surfaces

    input  - the Alleles pool of RNnases and SLFs
    output - E_pool_Ri_Fj an array of Interaction Energies between two alleles

    An Allele vector (RNase (R-allele)/ SLF (F-allele)) looks like this:
    Fj = {Fj1, Fj2, ... , FjL}
    Ri = {Ri1, Ri2, ... , RiL}
    L - is the length of the allele- a sequence of amino acids

    note - this function is called by 'initiate_haplotypes' only.
    Further needs of interaction calculations are calculated and saved as re-updating interactions dict
    '''
    raise NotImplementedError("Function has been masked for testing purposes")


def calc_female_fertilization_weights(diploid_count_dict, haplotypes_count_dict, delta_g_r_dict):
    """Calculate fertilization weights for all the diploids in the population based on the frequencies of the haplotypes that are able to fertilize them."""
    raise NotImplementedError("Function has been masked for testing purposes")

def calc_Rg_r_3D(offspring_dict, diploid_count_dict, delta_g_g_dict, cond1_g_g_dict, cond2_g_g_dict):

    # calculate R
    # given a genotype g and a foreign pollen with haploid genotype h / or a self pollen with haploid genotype g1 or g2
    # calculate the probability to produce an offspring with diploid genotype r

    R_g_g_r_dict = {}
    R_g_h_r_dict = {}

    # self fertilization
    for diploid_ind, diploid_i in enumerate(diploid_count_dict):
        diploid_i_lst = list(diploid_i)
        if delta_g_g_dict[diploid_i] == 0.5: # g is half self compatible
            is_C1 = cond1_g_g_dict[diploid_i] == 1
            is_C2 = cond2_g_g_dict[diploid_i] == 1
            if is_C1:
                offspring = [diploid_i[0], diploid_i[0]]
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[0]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 0.5
                offspring = diploid_i_lst
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[0]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 0.5
            if is_C2:
                offspring = [diploid_i[1], diploid_i[1]]
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[1]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 0.5
                offspring = diploid_i_lst
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[1]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 0.5
        if delta_g_g_dict[diploid_i] == 1: # g is fully self compatible
            if diploid_i[0] == diploid_i[1]: # g is homozygous,
                offspring = diploid_i_lst #the offspring and the parent are identicle
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[0]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 1
            else: # g is heterozygous
                offspring = diploid_i_lst # g is heterozygous the offspring and the parent are identicle
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[0]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 0.5
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[1]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 0.5
                offspring = [diploid_i[0], diploid_i[0]] # g is heterozygous, the offspring is homozygous
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[0]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 0.25
                offspring = [diploid_i[1], diploid_i[1]]
                g_h_r = tuple([item for sublist in [diploid_i_lst, [diploid_i[1]], offspring] for item in sublist])
                R_g_g_r_dict[g_h_r] = 0.25

    # foreign fertilizations
    for offspring_key, parents_values in offspring_dict.items():
        for parent in parents_values:
            haplotype_ind = parent[1]
            diploid_i = parent[0]

            g_h_r = tuple([item for sublist in [diploid_i, [haplotype_ind], list(offspring_key)] for item in sublist])
            if diploid_i[0] == diploid_i[1]:  # homozygosity
                if diploid_i == offspring_key:  # offspring equals diploid # i.e. g = S0S0, h = S0, r = S0S0
                    if diploid_i[0] == haplotype_ind:
                        R_g_h_r_dict[g_h_r] = 1

                else:  # the offspring r and the genotype g are not the same. # i.e. g = S0S0, h = S1, r = S0S1
                    if tuple([diploid_i[0], haplotype_ind]) == offspring_key or tuple(
                            [haplotype_ind, diploid_i[0]]) == offspring_key:
                        R_g_h_r_dict[g_h_r] = 1

            else:  # heterozygosity
                # the offspring r and the genotype g are not the same. # i.e. g = S0S1, h = S2, r = S0S2
                if tuple([diploid_i[0], haplotype_ind]) == offspring_key \
                        or tuple([haplotype_ind, diploid_i[0]]) == offspring_key \
                        or tuple([diploid_i[1], haplotype_ind]) == offspring_key \
                        or tuple([haplotype_ind, diploid_i[1]]) == offspring_key:
                    R_g_h_r_dict[g_h_r] = 0.5

    return R_g_g_r_dict, R_g_h_r_dict

def calc_pai_genotype_self_and_out(E_Ri_Fj_dict, haplotypes_dict, diploid_count_dict, haplotypes_count_dict,
                       delta_g_g_dict, delta_g_r_dict, cond1_g_g_dict, cond2_g_g_dict):

    '''
    input:
    E_Ri_Fj_dict - a dict with all alleles (RNases and SLFs in pool) interaction energies
    haplotypes_dict - a dict of all unique haplotypes' object
    diploid_count_dict - a dict of all unique diploid amounts
    haplotypes_count_dict - a dict of all unique haplotype amounts
    delta_g_g_dict -
    delta_g_r_dict -
    cond1_g_g_dict -
    cond2_g_g_dict -


    output:

    delta_g_g_dict, delta_g_r_dict, pai_g_g_self, pai_g_h_out, cond1_g_g_dict, cond2_g_g_dict


    pai_g_g_self - is the probability that an individual with a genotype g  is self-fertilized
                    ordered by the order of the diploids in "diploids_obj"


Complete the function implementation replacing "raise NotImplementedError".