Modélisation de l’évolution de la fréquence des allèles
Professeurs référents :
M FAURY (ISN)
Mme GOUHIER (SVT)
Objectif
Modéliser l’évolution des différents allèles d’un gène au cours du temps. Deux moteurs principaux sont responsables d’une modification des allèles :
- la dérive génétique,
- la sélection naturelle.
Ces deux facteurs induisent respectivement une modification aléatoire ou orientée de la fréquence des allèles dans une population.
Cahier des charges
A chaque génération, seuls certains allèles sont transmis par les parents à leur descendants. De la même façon, le logiciel doit modéliser un tirage au sort de certains allèles à partir d’une population de départ.
Paramètres d’entrée | Sorties graphiques |
|
|
Tâches à réaliser
Élève 1 (CLEMENT Arthur) |
Élève 2 (HERNANDEZ Martin) |
Élève 3 (WILLIAM Aurore) |
Représentation graphique d’une population | Interface utilisateur avec schéma | Algorithme de calcul |
La dérive génétique
Programme final
from tkinter import * from random import * import matplotlib matplotlib.use('TkAgg') from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg # implement the default mpl key bindings from matplotlib.backend_bases import key_press_handler from matplotlib.figure import Figure ############################################################################### # Constantes ############################################################################### couleurs = ["red","purple","green","yellow","blue"] # Liste de toutes les générations successives generations = [] z = 1 # un compteur d'individus # Liste de points pour les courbes X = [] Y = [] def allele(): n = scale2.get() # Nombre d'allèles différents return list(range(n)) def premiereG(): """ Construit une première génération (aléatoire) """ x=scale.get() # Nombre d'individus dans la population n=scale2.get() # Nombre d'allèles différents a=x//n gen=a*allele() for b in range(0,x%n): gen.append(b) shuffle(gen) return gen def Gsuivante(gen): """ Renvoie la génération suivante de gen """ a=entrée.get() x=scale.get() # Nombre d'individus dans la population gen2=[] for b in range(x): gen2.append(choice(gen)) if var.get()==1: for b in range(x): a=int(a) if a==randint(1,a): gen2[b]=randint(0,4) return gen2 def afficher(): if var.get()==1: label.grid(row=3, column=3, sticky='e', padx=55) entrée.grid(row=3, column=3, sticky='e',padx=20) elif var.get()==0: entrée.grid_forget() label.grid_forget() def demarrer(): """ Fonction lancée après appui sur le bouton "Démarrer" """ global generations, X, Y # On cache des choses ... scale.grid_forget() scale2.grid_forget() btn_demarrer.grid_forget() mutations.grid_forget() label.grid_forget() entrée.grid_forget() # On en affiche d'autres btn_tirer.grid(row=11, column=0) btn_tttirer.grid(row=11, column=1) btn_reinitialiser.grid(row=11, column=2) # Titre du bocal de droite C.create_text(120,230,text="Génération n°1") generations.append(premiereG()) plt.grid(True) plt.set_title("fréquence des allèles") plt.set_xlabel('génération') plt.set_ylabel('fréquence (%)') plt.axis([0,1,0,100]) plt.set_xticks(range(1)) nall = scale2.get() X = [] Y = [[] for i in range(nall)] for i, y in enumerate(Y): plt.plot(X, y) def reinitialiser(): global generations generations = [] scale.grid(row=1, column=3,padx=5,pady=5) scale2.grid(row=2, column=3,padx=5,pady=5) btn_demarrer.grid(row=4, column=3,padx=5,pady=5) mutations.grid(row=3, column=3,padx=5,pady=5) btn_tirer.grid_forget() btn_tttirer.grid_forget() btn_tirerBis.grid_forget() btn_tttirerBis.grid_forget() btn_reinitialiser.grid_forget() btn_generation.grid_forget() mutations.deselect() B.delete(ALL) B.create_line(18,20,18,222,18,222,222,222,222,222,222,20) C.delete(ALL) C.create_line(18,20,18,222,18,222,222,222,222,222,222,20) plt.cla() fig.canvas.draw() def tirer(bocal, gen, z): """ Place l'allele de l'individu "z" de génération "gen" dans le bocal """ x = scale.get() y = gen[z-1] if z < x: if z<11: a=20*(z) b=20*(z+1) bocal.create_oval(a,200,b,220, fill=couleurs[y], width=0) if 10<z<21: a=20*(z-10) b=20*(z-9) bocal.create_oval(a,180,b,200, fill=couleurs[y], width=0) if 20<z<31: a=20*(z-20) b=20*(z-19) bocal.create_oval(a,160,b,180, fill=couleurs[y], width=0) if 30<z<41: a=20*(z-30) b=20*(z-29) bocal.create_oval(a,140,b,160, fill=couleurs[y], width=0) if 40<z<51: a=20*(z-40) b=20*(z-39) bocal.create_oval(a,120,b,140, fill=couleurs[y], width=0) if 50<z<61: a=20*(z-50) b=20*(z-49) bocal.create_oval(a,100,b,120, fill=couleurs[y], width=0) if 60<z<71: a=20*(z-60) b=20*(z-59) bocal.create_oval(a,80,b,100, fill=couleurs[y], width=0) if 70<z<81: a=20*(z-70) b=20*(z-69) bocal.create_oval(a,60,b,80, fill=couleurs[y], width=0) if 80<z<91: a=20*(z-80) b=20*(z-79) bocal.create_oval(a,40,b,60, fill=couleurs[y], width=0) if 90<z: a=20*(z-90) b=20*(z-89) bocal.create_oval(a,20,b,40, fill=couleurs[y], width=0) else: btn_tirer.grid_forget() btn_generation.grid(row=11, column=1) btn_tttirer.grid_forget() tracer() def incrementer_generations(): btn_generation.grid_forget() generations.append(Gsuivante(generations[-1])) global z i=len(generations) z=1 if i%2==1: B.grid(row=1, column=0, rowspan=10) C.grid(row=1, column=1, rowspan=10) C.delete(ALL) C.create_line(18,20,18,222,18,222,222,222,222,222,222,20) btn_tirer.grid(row=11, column=0) btn_tirerBis.grid_forget() btn_tttirer.grid(row=11, column=1) btn_tttirerBis.grid_forget() C.create_text(120,230,text="Génération n°"+str(i)) else: C.grid(row=1, column=0, rowspan=10) B.grid(row=1, column=1, rowspan=10) B.delete(ALL) B.create_line(18,20,18,222,18,222,222,222,222,222,222,20) btn_tirerBis.grid(row=11, column=0) btn_tirer.grid_forget() btn_tttirerBis.grid(row=11, column=1) btn_tttirer.grid_forget() B.create_text(120,230,text="Génération n°"+str(i)) def tttirer(bocal, gen): """ Termine de placer toutes les allèles de la génération "gen" à partir de l'individu "z" """ global z x = scale.get() btn_tirer.grid_forget() btn_tttirer.grid_forget() while z-1 < x: tirer(bocal, gen, z) z += 1 def decompte(gen): """ Renvoie une liste de décompte du nombre d'allèle dans la génération "gen" """ frequence=[] a={} for b in gen: if b in a.keys(): a[b]+=1 else: a[b]=1 nall = scale2.get() for c in range(nall): if c in a.keys(): frequence.append(a[c]) else: frequence.append(0) y = len(gen) # On met les quantité en % frequence = [i/y*100 for i in frequence] return frequence def tracer(): global X, Y X = list(range(len(generations))) nall = scale2.get() for i, f in enumerate(decompte(generations[-1])): Y[i].append(f) c = ['r', 'm', 'g', 'y', 'b'] c = c[:nall] plt.cla() for i, y in enumerate(Y): plt.plot(X, y,c[i]) fig.canvas.draw() ############################################################################### fenetre = Tk() fenetre.title("Modélisation de l’évolution de la fréquence des allèles") fenetre['bg']='bisque' titre = Label(fenetre, text="Modélisation de l’évolution de la fréquence des allèles", bg='bisque') titre.configure(fg = 'gray') titre.grid(row=0, column=0, columnspan=100) #fenetre.minsize(955,527) #fenetre.maxsize(955,527) scale=Scale(orient='horizontal', from_=5, to=100, resolution=1, tickinterval=10, length=400, activebackground='black', bg='gray', bd=5, fg='white', label="Nombre d'individus dans la population", troughcolor='white') scale.grid(row=1, column=3,padx=5,pady=5) scale2=Scale(orient='horizontal', from_=2, to=5, resolution=1, tickinterval=1, length=200, activebackground='black', bg='gray', bd=5, fg='white', label="Nombre d'allèles différents", troughcolor='white') scale2.grid(row=2, column=3,padx=5,pady=5) entrée=Entry(width=5) label=Label(text="1/") var = IntVar() mutations = Checkbutton(fenetre, text="Autoriser les mutations", bg='gray', command=afficher, variable=var) mutations.grid(row=3, column=3,padx=5,pady=5) btn_demarrer = Button(fenetre, text = "Démarrer", command = demarrer) btn_demarrer.grid(row=4, column=3,padx=5,pady=5) btn_tirer = Button(fenetre, text = "tirer une boule", command=lambda: tirer(C, generations[-1], z)) btn_tirerBis = Button(fenetre, text = "tirer une boule", command=lambda: tirer(B, generations[-1], z)) btn_tttirer = Button(fenetre, text = "tout tirer", comman=lambda: tttirer(C, generations[-1])) btn_tttirerBis = Button(fenetre, text = "tout tirer", comman=lambda: tttirer(B, generations[-1])) btn_reinitialiser= Button(fenetre, text = "réinitialiser", command = reinitialiser) btn_generation= Button(fenetre, text ="génération suivante", command = incrementer_generations) # Les bocaux B=Canvas(width=240, height=240) B.grid(row=1, column=0, rowspan=10,padx=10,pady=10) B.create_line(18,20,18,222,18,222,222,222,222,222,222,20) C=Canvas(width=240, height=240) C.grid(row=1, column=1, rowspan=10,padx=10,pady=10) C.create_line(18,20,18,222,18,222,222,222,222,222,222,20) ############################################################################### # Zone du graphique ############################################################################### z_plot = Frame(fenetre) fig = Figure(figsize=(5, 4), dpi=100) plt = fig.add_subplot(111) # a tk.DrawingArea canvas = FigureCanvasTkAgg(fig, master=z_plot) canvas.show() canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) toolbar = NavigationToolbar2TkAgg(canvas, z_plot) toolbar.update() canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1) z_plot.grid(row=12, column=0, columnspan=3,padx=10,pady=10) fenetre.mainloop()[/reveal]
La sélection naturelle
La sélection des allèles n’est dans ce cas plus aléatoire, mais dépend d’un facteur influençant leur transmission (paramètres de l’environnement, action d’un prédateur, …)
Bonjour, je suis très intéressée par votre projet » modélisation de l’évolution de la fréquence des allèles » cependant je suis une débutante je ne sais pas par où commencer ni comment m’y prendre. pouvez vous m’aidez pour que ce projet soit au top 🙂
Bonjour
Je ne peux pas faire beaucoup mieux que de vous renvoyer vers le code Python fourni au bas de cet article. Il est très largement perfectible, mais suffisamment commenté pour se l’approprier…
Ça peut constituer un solide point de départ, non ?
MERCI votre commentaire nous a beaucoup aider mais nous avons un problème avec la fonction « matplotlib » pouvez vous nous éclairer s’il vous plait
Bonjour
Je vous renvoie vers un très bon article qui explique tout : https://openclassrooms.com/fr/courses/4452741-decouvrez-les-librairies-python-pour-la-data-science/4740942-maitrisez-les-possibilites-offertes-par-matplotlib
bonjour ! Desolee pour le dérangement mas y aurait-il moyen s’il vous plait de me fournir de facon detaille le fonctionnement des boucles parce que je ne comprend pas grand chose et pourtant je le trouve très complet et fort interessant
merci de votre comprehension et pour votre aide
bonjour ! Desolee pour le dérangement mas y aurait-il moyen s’il vous plait de me fournir de facon detaille le fonctionnement des boucles parce que je ne comprend pas grand chose et pourtant je le trouve très complet et fort interessant
merci de votre comprehension et pour votre aide qui a été très utile dans l’avancement de mon travail