Réunion 11/02/26

Lionel Viguier

Ordre du jour

  • Présentation du travail sur l’issue 7 (encore).
  • Issue 6: handle missing one parent in pedigree data.
  • Présentation des tests.
  • Création des Issues 10 et 11
  • Partie discussion.

Issue 7 gestion des PedNode grace a des indexes

La semaine dernière le choix de la solution (pednode.idx) c’est avéré mauvais. La solution a implémenter est: l’utilisation d’un Dictionnaire ‘indiv’->‘index’ présent dans le Pedigree

Changements a implémenter:

  • modifier la fonction d’ajout d’individus add_indiv pour MAJ le dictionnaire
# Overwrite
def add_indiv(self, indiv):
    """Add a new guy to the pedigree"""
    if indiv in self.nodes:
        logger.debug(f"{indiv} is already there")
    else:
        self.nodes[indiv] = self.node_class(indiv)
        self.idx_dict[indiv] = self.__current_idx
        self.__current_idx += 1
  • utiliser le dictionnaire pour récupérer les indexe
indk_id = self.d.ped.idx_dict[indk.indiv]

Probleme non résolu:

Classe Family est un objet itératif qui permet d’obtenir efficacement chaque enfants d’un couple donné.

les objets familles sont stocker dans un tenseur dont la premiere dimension correspond a: id mâle, id femelle, idx family.

self.ind_to_fam = np.vstack(
[np.append(fam.parents_id, fam.idn) for fam in self.ped.fam_peel.values()]
)
self.ind_to_fam.view("i8,i8,i8").sort(order=["f2"], axis=0)

⚠️ suite aux modifications fam.parents_id renvoie des ‘str’ et pas des ‘int’.

Probleme non résolu:

Utilité de ind_to_fam

Cette fonction n’a pas encore été implémenter, mais elle permatrais un gain d’efficacitée.

def update_conditional_probabilities(self):
    self.d.pi_Pfj_minusfam[..., self.d.ind_to_fam[..., 2]] = (
        self.d.pi_Pij[..., self.d.ind_to_fam[:, MALE]]
        - self.d.Pij[..., self.d.ind_to_fam[..., 2], MALE]
    )
    self.pi_Pmj_minusfam[..., self.d.ind_to_fam[..., 2]] = (
        self.d.pi_Pij[..., self.d.ind_to_fam[:, FEMALE]]
        - self.d.Pij[..., self.d.ind_to_fam[..., 2], FEMALE]
    )

Issue 6: handle missing one parent in pedigree data.

When one parent is “0” in fam -> set to None, cannot impute in peeling.

@classmethod 
def from_fam_file(cls,path,parent_from_FID=False,
    default_parent=MALE,UnknownParentPrefix="peel_unk_",):
    [...]
    if (fa is None) ^ (mo is None): # <- xor
        # If only one parents is missing then we create it
        c += 1
        if fa is None:
            fa = UnknownParentPrefix + "fa_" + str(c)
        else:
            mo = UnknownParentPrefix + "mo_" + str(c)
    relations.append((ind, fa, mo))

Tests

test de “l’indexage”

Pour tester si les indexes sont bien attribuer on charge des fichier de génotypages avec des lignes mélangées, et on les charges a partir du meme pédigrée.

L’ordre des deux génotypage doivent etre identique car basé sur les indexes du Pedigree.

geno_ctrl = pl.LoadGenotypes(genfile,ped,',')
geno_shuff = pl.LoadGenotypes(genfile_shuffled,ped,',')
test = np.array(geno_ctrl == geno_shuff)
if np.prod(test) != 0: 
#si les deux lectures matches ( en booléen * = And , + = Or)
    print ("test de chargement de génotype: validé")
else:
    print ("test de chargement de génotype: échec ")

Tests

Tester si les alleles freq des founders sont modifiés

ip = pl.buildIterativePeeling(pedfile,genfile) # création de l'objet
founderList = [i.indiv for i in ped.founders]
founderIDX_List = [ped.idx_dict[i] for i in founderList]

antdeb =  ip.d.anterior
antFoundersDEB = [antdeb[:,:,i] for i in founderIDX_List]

ip.RunPeeling()

test = np.array(antFoundersDEB == ip.d.pop_freq)
if np.prod(test) != 0: 
    print ("test de founders's anterior: échec")
else:
    print ("test de founders's anterior: validé")

Tests

Tester l’imputation du Peeling itératif:

testImput = pl.buildIterativePeeling("genotype_fernando.ped",
    "genotype_fernando12missing.csv")
testImput.RunPeeling()
res =  [np.where(i == max(i))[0][0] for i in testImput.d.peeling[...,11]]
geno_ctrl[11,...] == np.ravel(res)
#Out[25]: 
array([ True,True,True,True,True,True,True,True,True,False])

On a un génotype mal imputer pour un locus, si on regarde plus précisément le likelyhood générer pour ce dernier locus on a alors:

testImput.d.peeling[9,:,11]
#Out[26]: array([-21.56189546, -17.69832648, -17.7429063 ])

le bon génotype est 2 mais le génotype le plus probable est 1

Création des Issues 10 et 11

Issue 10

Un bug a été identifier quand on lance le peeling: les valeurs des anteriors des fondateurs ne sont jamais mises a jours. Aussi les fréquence allélique dans la population ne sont calculer qu’une fois au début du Peeling.

Création des Issues 10 et 11

Issue 11

La création de l’issue 10 a refait émerger la question de la création d’une blacklist. Cette blacklist d’individus a ne pas mettre a jours permet de ne pas calculer de likelyhood de certains individus dont l’imputation est impossible faute d’information.

Les individus a blacklister serait:

  • les individus générer lors de la lecture du pédigée (issue 6)
  • les individus non génotyper sans enfants génotyper
  • j’imagine pleins d’autres aussi…

Discussion

  1. Pour l’issue 6 seul from_fam_file a été modifier
  2. Les résultats de l’imputation
  3. La Blacklist
    1. quoi mettre dedans
    2. comment skip certains individus
  4. La fonction update_conditional_probabilities
  5. je n’ai pas pu tester le jdd PorcQTL, je n’arrive pas a charger le VCF

Taches:

  • Changer le nom des individus générer (quand un des deux parents est absent du pédigree) nouvel id: indiv.indiv + “_fa”.
  • Changer l’issue 11: BlackList -> Pruning
    • tester le pruning avec le pédigree complet d’Elise
  • Vérifier le calcul des frequences allelique.
    • on peut regarder l’évolution de l’estimation de popFreq si on a la vrais popFreq
  • Mettre a jours les Anterior des Founders a chaque Cycle ie recalculer les frequences allelique