]> git.immae.eu Git - perso/Denise/oms.git/blob - trace_courbe.py
Version 2.6 plus : pas mal de changements (voir changelog)
[perso/Denise/oms.git] / trace_courbe.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 from configuration import CONFIG
4 import gestionOMS as oms
5 import gestion_unites as u
6 from gestion_donnees import calcule_max_graphique, convertit_jours_vers_python, simplifie_nom
7 from gestion_erreurs import debug, erreur, warning
8 from calculs_extrapole import calcule_donnee_extrapolee, calcule_age_extrapole, interpole_lineaire, interpole_lineaire_ordonnee, formate_resultat_donnee, formate_resultat_age, formate_interpole, formate_extrapole
9 import datetime
10
11 from numpy import arange
12
13
14 import matplotlib.pyplot as plt
15
16 # Essentiellement, la fonction qui trace la courbe, mais on y trouve également les fonctions d'extrapolation.
17 # Ainsi que les calculs additionnels.
18
19
20 def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err, enfants_add = []):
21 """ conf est le dictionnaire de config. l_jours et l_poids les listes des temps (en jours) et de données
22 (donc pas forcément du poids)
23 typedonnee est le type de données (voir CONFIG["liste_typedonnees"]
24 liste_err la liste des erreurs à compléter (voir gestion_erreurs))
25 Renvoie la figure tracée, et les calculs additionnels sont mis sous forme de chaîne dans la liste
26 liste_extracalculs
27
28 Les enfants en plus sont dans la liste enfants_add. Pour chaque item de la liste, il faut prendre
29 item[typed] pour avoir accès au nom, ljours, et ldonnees
30
31 """
32 debug("debut de cree_figure. Config : "+str(conf)+". Nombre d'enfants additionnels : "+str(len(enfants_add)),liste_err)
33 try:
34 liste_data_labels_p,liste_data_labels_z = oms.renvoie_liste_labels(conf,CONFIG["liste_data_choisie_p"],CONFIG["liste_data_choisie_z"],liste_err)
35 except:
36 erreur("bug avec liste data labels",liste_err)
37 return ""
38
39 ######################## Gestion des bornes #############################
40 # y a-t-il un maxi saisi par l'utilisateur ?
41 if conf["maxi"] ==0:
42 # Est-ce qu'on a donné un maxi quand même (car même échelle) ?
43 if conf["non_sauve"].get("maxi",0) == 0:
44 jour_maxi = calcule_max_graphique(l_jours)
45 else:
46 jour_maxi = conf["non_sauve"]["maxi"]+1
47 else:
48 jour_maxi = conf["maxi"]+1
49
50 # Si on cherche à extrapoler au-delà
51 if conf["non_sauve"]["calculextradata_type"] == typedonnee and conf["non_sauve"]["calculextradata_age"]>jour_maxi:
52 jour_maxi = int(conf["non_sauve"]["calculextradata_age"]) +1
53
54 # On s'assure que c'est bien compris dans les bornes
55 jour_maxi = max(CONFIG["jours_mini_courbe"],min(jour_maxi,CONFIG["jours_maxi_courbe"]))
56 debug("cree_figure : gestion du jour max : "+str(jour_maxi),liste_err)
57
58 ##################### Gestion des unités ###############################
59 # si l'unité n'est pas précisée, ni en "non sauvé" ni par l'utilisateur
60 if conf["unite"] == "" and conf["non_sauve"].get("unite","") == "":
61 unite = u.choix_unite(jour_maxi)
62 debug("Unité non précisée, on choisit "+unite,liste_err)
63 elif conf["unite"] != "":
64 unite = conf["unite"]
65 else:
66 unite = conf["non_sauve"]["unite"]
67
68 ##################### Gestion de la prématurité #######################"
69 prema = int(convertit_jours_vers_python(conf["prematurite"],liste_err))
70 ## Gestion des prémas, deux cas :
71 # Si agecorrige est oui, alors on veut juste soustraire la valeur de préma
72 # à toutes les données.
73 # Si agecorrige est non, alors on veut ajouter la valeur de préma aux courbes de référence.
74 debug("Prématurité : "+str(prema)+" age corrigé : "+conf["agecorrige"],liste_err)
75 if prema>0 and conf["agecorrige"] == "oui":
76 l_jours = [j-prema for j in l_jours]
77 jour_maxi = jour_maxi - prema
78
79
80 ###################### Conversion des unités ###########################""
81 l_jours_conv = u.convertit_tableau(l_jours,unite,liste_err)
82 # Attention, comme les jours commencent à partir de 0, faut enlever 1 pour avoir la borne...
83 age_maxi = u.convertitunite(jour_maxi-1,unite,liste_err)
84
85 debug("cree_figure : conversion des unités ok : "+str(l_jours_conv),liste_err)
86
87 #####################" Courbes OMS et titre ######################################"
88 titre = "Courbe de "+typedonnee+" OMS"
89 if conf["typecourbe"] == "P":
90 # percentiles
91 liste_data_labels = liste_data_labels_p
92 if conf["sexe"] == "M":
93 fichier_oms = CONFIG["fichiersOMS"][typedonnee]["perc_garcon"]#f_poids_perc_garcon
94 titre += " (percentiles, garçon)"
95 elif conf["sexe"] == "F":
96 fichier_oms = CONFIG["fichiersOMS"][typedonnee]["perc_fille"]
97 titre += " (percentiles, fille)"
98 else:
99 fichier_oms = CONFIG["fichiersOMS"][typedonnee]["perc_mixte"]
100 titre += " (percentiles)"
101 elif conf["typecourbe"] == "Z":
102 liste_data_labels = liste_data_labels_z
103 if conf["sexe"] == "M":
104 fichier_oms = CONFIG["fichiersOMS"][typedonnee]["z_garcon"]
105 titre += " (moyenne et écarts-types, garçon)"
106 elif conf["sexe"] == "F":
107 fichier_oms = CONFIG["fichiersOMS"][typedonnee]["z_fille"]
108 titre += " (moyenne et écarts-types, fille)"
109 else:
110 fichier_oms = CONFIG["fichiersOMS"][typedonnee]["z_mixte"]
111 titre += " (moyenne et écarts-types)"
112 else:
113 erreur("Type de courbe invalide"+conf["typecourbe"],liste_err)
114 return ""
115
116 ## On finira le titre plus tard quand on aura su qui est concerné
117
118 #debug("cree_figure : géré le type de courbe ok. Liste des data labels : "+str(liste_data_labels),liste_err)
119 debug("Fichier d'où extraire les données : "+fichier_oms,liste_err)
120
121
122 #### On extrait les données des courbes, et on convertit les jours dans l'unité voulues
123 try:
124 t = oms.lire_fichier_csv(fichier_oms)
125 except:
126 erreur("cree_figure : Impossible d'ouvrir le fichier "+fichier_oms, liste_err)
127 return ""
128
129 debug("cree_figure : Conversion des données OMS à la bonne unité",liste_err)
130 try:
131 coljour= (oms.extraire_colonne(t,0,jour_maxi))
132 if prema>0 and conf["agecorrige"] != "oui":
133 coljour = [j + prema for j in coljour]
134 coljour = u.convertit_tableau(coljour,unite,liste_err)
135 except:
136 erreur("Problème à la conversion du tableau OMS. jour_maxi = "+str(jour_maxi)+" unite = "+unite,liste_err)
137 return ""
138
139 ##################### Création de la figure et du graphique ###################
140 debug("cree_figure : prête à créer la figure",liste_err)
141 #### La figure, params
142
143 fig = plt.figure(num=None, figsize=(conf["largeur"], conf["hauteur"]), dpi=100, facecolor=conf["couleurs"]["fond"])
144 plt.rcParams['axes.facecolor'] = conf["couleurs"]["fond"]
145 plt.rcParams['axes.edgecolor']= conf["couleurs"]["cadretxt"]
146 plt.rcParams['xtick.color'] = conf["couleurs"]["cadretxt"]
147 plt.rcParams['ytick.color'] = conf["couleurs"]["cadretxt"]
148 plt.rcParams['grid.color'] = conf["couleurs"]["grille"]
149 plt.rcParams['legend.edgecolor'] = conf["couleurs"]["grille"]
150 ax = plt.axes()
151
152 ###################### Tracé des différentes courbes
153 #Tracé des courbes OMS
154 for (i,label,couleur) in liste_data_labels:
155 ax.plot(coljour,oms.extraire_colonne(t,i,jour_maxi),label=label,color=couleur)
156
157 debug("cree_figure : tracé des courbes OMS ok",liste_err)
158
159 ### Tracé pour de bon
160 if l_jours != []:
161 print(conf["symbole"])
162 ax.plot(l_jours_conv,l_poids,label=conf["nom"],color=conf["couleurs"]["courbeenfant"],marker=conf["symbole"])
163 debug("Tracé de la courbe enfant, avec les jours "+str(l_jours_conv),liste_err)
164
165
166 listenoms = []
167 if conf["nom"] != "": # Ajouter le nom de l'enfant
168 listenoms.append(conf["nom"])
169
170 # if enfants_add != []:
171 # debug("Il y a des enfants en plus à tracer. Données : "+str(enfants_add), liste_err)
172 for enfant in enfants_add: # Enfants additionnels éventuels
173 conf_add, lj, ld = enfant[typedonnee] # On récuère les données
174 if lj != []: # pas la peine de tracer si y'a rien à tracer
175 # Ajouter le nom de cet enfant-là
176 listenoms.append(conf_add["nom"])
177 # Le mot "courbe" doit être au pluriel du coup !
178 titre = titre.replace("Courbe ", "Courbes ")
179 lj_conv = u.convertit_tableau(lj,unite,liste_err)
180 debug("Tracé de la courbe additionnelle de "+conf_add["nom"]+" config : "+str(conf_add), liste_err)
181 ax.plot(lj_conv, ld, label=conf_add["nom"], color=conf_add["couleurcourbe"],marker=conf_add["symbole"])
182
183 if conf["sexe"] != conf_add["sexe"]:
184 warning("Attention, tous les enfants n'ont pas le même sexe. La courbe de référence est celle de "+conf["nom"]+" et ne sera pas forcément pertinente pour les autres. Vous pouvez éventuellement essayer la courbe neutre. Remarque : cette alerte s'affichera quand même.", liste_err)
185
186
187 # Si y'a un nom on met "courbe de machin, de bidule, d'alala, de truc"
188 for i in range(len(listenoms)):
189 # Mot de liaison : , ou et ?
190 if i>0 and i!=len(listenoms)-1:
191 titre += ", "
192 elif i>0 and i == len(listenoms) -1:
193 titre+= " et "
194 else:
195 titre += " "
196 # Est-ce que la première lettre est une voyelle ?
197 lettre = simplifie_nom(listenoms[i]).lower()[0]
198 if lettre in CONFIG["voyelles"]:
199 titre += "d'"
200 else:
201 titre += "de "
202 titre += listenoms[i]
203
204 if prema>0:
205 titre+= ", préma de "+conf["prematurite"]
206 if conf["agecorrige"] == "oui":
207 titre+=" (courbe en âge corrigé)"
208 else:
209 titre+=" (courbe en âge réel, données OMS décalées)"
210
211 #### extrapolatios éventuelles
212 # a-t-on demndé des calculs ?
213 jextrapole = conf["non_sauve"]["prolongercourbes"] == "oui"
214 # Est-ce qu'on a demandé un calcul sur cette donnée ?
215
216 for calextra in CONFIG["extradata"]:
217 jextrapole = jextrapole or conf["non_sauve"][calextra+"_type"] == typedonnee
218
219 #print(jextrapole)
220 ############################## Là où on extrapole ################################
221 if jextrapole:
222 try:
223 debug("Il faut extrapoler les courbes !", liste_err)
224 # Prendre l'ensemble des dates "source"
225 # print(conf["non_sauve"]["nbdataextra"])
226 if conf["non_sauve"]["nbextradata"] == 0:
227 sources_extrap = l_jours
228 sources_extrap_data = l_poids
229 else:
230 sources_extrap = l_jours[-conf["non_sauve"]["nbextradata"]:] # les derniers jours
231 sources_extrap_data = l_poids[-conf["non_sauve"]["nbextradata"]:]
232
233 debug("On extrapole sur les jours : "+str(sources_extrap), liste_err)
234
235 # On récupère toutes les données extrapolées
236 dates_extrapole, donnees_extrapole = prolongecourbe(t, sources_extrap, sources_extrap_data, conf["typecourbe"], liste_err)
237 debug("données extrapolées !", liste_err)
238 #debug(str(dates_extrapole[0:10])+str(donnees_extrapole[0:10]), liste_err)
239
240 # QUe veut-on maintenant sur ces données extrapolées ?
241 # Afficher la courbe
242 if conf["non_sauve"]["prolongercourbes"] == "oui":
243 # On va prendre les extrapolations de la dernière donnée jusqu'à l fin du graphe
244 debut_extr = int(l_jours[-conf["non_sauve"]["nbextradata"]])
245 i_debut_extr = dates_extrapole.index(debut_extr)
246 if jour_maxi >= dates_extrapole[-1]:
247 i_fin_extr = len(dates_extrapole) -1
248 else:
249 i_fin_extr = dates_extrapole.index(jour_maxi)
250 print("bla", i_debut_extr, i_fin_extr)
251 # Voilà ce qu'on veut tracer
252 dates_extrapole_trace = dates_extrapole[i_debut_extr:i_fin_extr+1]
253 donnees_extrapole_trace = donnees_extrapole[i_debut_extr:i_fin_extr+1]
254 dates_extrapole_trace = u.convertit_tableau(dates_extrapole_trace,unite,liste_err)
255
256 # tracé des données extrapolées
257 plt.plot(dates_extrapole_trace, donnees_extrapole_trace,color=conf["couleurs"]["cadretxt"], linestyle=(0, (5,7)), marker=None)
258 debug("Tracé de la courbe extrapolée ok", liste_err)
259
260 ### Calculer une donnée à l'âge x
261 if conf["non_sauve"]["calculextradata_type"] == typedonnee:
262 # On essaie l'interpolation
263 r = interpole_lineaire(l_jours,l_poids,conf["non_sauve"]["calculextradata_age"], liste_err)
264 if r==-1:
265 # ça sera donc une extrapolation
266 r = calcule_donnee_extrapolee(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextradata_age"], liste_err)
267 message=formate_extrapole(conf["non_sauve"]["nbextradata"])
268 else:
269 message=formate_interpole()
270
271 texte = formate_resultat_donnee(conf["non_sauve"]["calculextradata_age"], conf["non_sauve"]["calculextradata_date"], r, typedonnee, message, liste_err)
272 debug("calcul de la donnée extrapolée : "+texte, liste_err)
273 if texte!="":
274 liste_extracalculs.append(texte)
275 #print(liste_extracalculs)
276 # Ajouter le trait ?
277 if conf["non_sauve"]["calculextradata_trace"] == "oui":
278 dessine_guides(conf["non_sauve"]["calculextradata_age"], r, conf["couleurs"]["cadretxt"], unite, ax, liste_err)
279
280 ### Calculer un âge où on atteint cette donnée
281 if conf["non_sauve"]["calculextratemps_type"] == typedonnee:
282 # interpolation
283 r = interpole_lineaire_ordonnee(l_jours,l_poids,conf["non_sauve"]["calculextratemps_val"], liste_err)
284 if type(conf["naissance"]) == datetime.date:
285 rdate = conf["naissance"] + datetime.timedelta(days=r)
286 else:
287 rdate = None
288
289 if r==-1:
290 # ça sera donc une extrapolation
291 r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], liste_err)
292 if type(conf["naissance"]) == datetime.date:
293 rdate = conf["naissance"] + datetime.timedelta(days=round(r))
294 else:
295 rdate = None
296 message=formate_extrapole(conf["non_sauve"]["nbextradata"])
297 else:
298 message=formate_interpole()
299 print(r, rdate)
300 texte = formate_resultat_age(r, rdate, conf["non_sauve"]["calculextratemps_val"], typedonnee, message, liste_err)
301
302 #r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], typedonnee, liste_err)
303 if texte!="":
304 liste_extracalculs.append(texte)
305 print(liste_extracalculs)
306 # Ajouter le trait ?
307 if conf["non_sauve"]["calculextratemps_trace"]:
308 dessine_guides(r, conf["non_sauve"]["calculextratemps_val"], conf["couleurs"]["cadretxt"], unite, ax, liste_err)
309
310 except:
311 warning("Des problèmes pour extrapoler...", liste_err)
312
313 else:
314 debug("On ne trace pas de courbe enfant", liste_err)
315
316 ###################" Gestion de l'échelle #####################
317 debug("Courbes tracées. Il n'y a plus qu'à gérer l'échelle", liste_err)
318 ### échelle à régler
319
320 # On extrait la valeur min et la valeur max des poids des courbes OMS et des données
321 (colonne_min,_,_) = liste_data_labels[-1]
322 (colonne_max,_,_) = liste_data_labels[0]
323
324 # poids max OMS
325 poids_min = min(oms.extraire_colonne(t,colonne_min,jour_maxi))
326 poids_max = max(oms.extraire_colonne(t,colonne_max,jour_maxi))
327 if l_jours != []:
328 poids_min = min(min(l_poids),poids_min)
329 # Pour le poids max, voir la dernière valeur du tableau
330 i = 0
331 while i<len(l_jours) and l_jours[i]<jour_maxi:
332 i=i+1
333 poids_max = max(max(l_poids[0:i+1]),poids_max)
334 # On ajuste un peu ces min et max
335 # min : valeur min -1kg
336 poids_min = max(0,poids_min-1)
337 #max : +5%
338 poids_max = poids_max * 1.05
339
340
341 ### Repères additionnels éventuels.
342 #reperes est une liste qui contient des dictionnaires avec "typed" (type de donnée : âge, etc), "donnee" :
343 #la donnée (en jours pour l'âge), et "texte": le texte à mettre sur le repère en question.
344 #Pour tracer des repères verticaux (horizontaux plus tard) sur la courbe.
345 for rep in conf["liste_reperes"]:
346 if rep.get("trace", "") == "oui": # SI on veut tracer
347 agec = u.convertitunite(rep["donnee"], unite, liste_err)
348 # Tracé de la ligne verticale
349 ax.vlines(agec, poids_min, poids_max, linestyles="dashed", color=conf["couleurs"]["cadretxt"])
350 # date à afficher ?
351 if rep["affichedate"] == "oui" and rep["date"] != "":
352 ax.text(agec, poids_min,rep["date"]+" ", rotation=90, verticalalignment='top', horizontalalignment='center', color=conf["couleurs"]["cadretxt"], fontstyle="italic")
353 # Si y'a un texte à afficher
354 if rep["texte"] != "":
355 ax.text(agec, poids_min, " "+rep["texte"], rotation=90, verticalalignment='bottom', horizontalalignment='right', color=conf["couleurs"]["cadretxt"])
356
357
358
359
360
361 # Grille custom ?
362 if conf["non_sauve"]["grilleamelio"] == "oui":
363 debug("On a choisi la grille plus jolie", liste_err)
364 pas=u.choix_echelle_data(typedonnee, poids_max)
365 # data_min_arrondie
366 minechelle = int(poids_min/pas[0])*pas[0]
367
368 debug("pas choisis pour l'échelle en y : "+str(pas), liste_err)
369 echellemajeure = arange(minechelle, poids_max, pas[0])
370
371 if pas[1] >0:
372 echellemineure = arange(minechelle, poids_max, pas[1])
373 else:
374 echellemineure = []
375
376 ax.set_yticks(echellemajeure, minor=False)
377 ax.set_yticks(echellemineure, minor=True)
378
379 # échelle en temps
380 pas=u.choix_echelle_temps(unite, age_maxi)
381 debug("pas choisis pour l'échelle en x : "+str(pas), liste_err)
382
383 echellemajeure = arange(0,age_maxi, pas[0])
384 if pas[1] >0:
385 echellemineure = arange(0,age_maxi, pas[1])
386 else:
387 echellemineure = []
388 ax.set_xticks(echellemajeure, minor=False)
389 ax.set_xticks(echellemineure, minor=True)
390
391 ################################# Aspect du graphique
392
393 debug("On commende la déco du graphique", liste_err)
394
395 # La grille
396 ax.grid(conf["grille"]=="oui")
397 ax.grid(conf["grille"] == "oui", which="minor", linestyle="--")
398
399
400 plt.xlabel("Âge en "+unite,color=conf["couleurs"]["cadretxt"])
401 plt.ylabel(typedonnee.capitalize()+" en "+CONFIG["unites_typedonnees"][typedonnee],color=conf["couleurs"]["cadretxt"])
402 plt.title(titre,color=conf["couleurs"]["cadretxt"])
403 if l_jours_conv == []:
404 plt.axis([0,age_maxi, poids_min, poids_max])
405 else:
406 plt.axis([min(0,l_jours_conv[0]),age_maxi,poids_min,poids_max])
407
408
409 if conf['legende']=="oui":
410 legende = plt.legend(loc=conf['positionlegende'])
411 plt.setp(legende.get_texts(), color=conf["couleurs"]["cadretxt"])
412
413
414 fig.tight_layout()
415
416 debug("Fin de cree_figure, tout va bien.", liste_err)
417 return fig
418
419
420
421
422 ######################################## Pour extrapoler la courbe
423
424 def prolongecourbe(tableauOMS, dates, donnees, typecourbe, liste_err):
425 """ tableauOMS est le ableau des données OMS. dates et donnees sont les dates (jours)
426 et les données d'où on extrapole. On calcule toutes les dates comme des sauvages.
427 On renvoie la liste des jours totale et la liste des data_totales
428 (tableaux de jours)
429 typecourbe est P ou Z. Pour P il faut commencer à regarder à l'indice 4, pour Z
430 à l'indice 1
431 On renvoie [],[] si pas pu extrapoler. """
432 # les lignes OMS correspondant aux dates données
433 lignesoms = [tableauOMS[int(date)] for date in dates]
434 debug("prolongecourbe : Lignes OMS :"+str(lignesoms)+" valeur de données : "+str(donnees), liste_err)
435
436
437
438 # Principe : on cherche dans quel intervalle de "colonnes" on se situe.
439 # On va donc regarder pour chaque donnée entre quels i on se situe,et après
440 # prendre le plus grand intervalle.
441 # Numéros de colonnes d'où on part. Pour la fin c'est forcément longueur-1
442 if typecourbe == "P":
443 idep=4
444 else:
445 idep = 1
446
447 liste_indices = []
448 for k in range(len(dates)):
449 i= idep
450 ligne = lignesoms[k]
451 while i<len(ligne) and ligne[i]<donnees[k]:
452 i+=1
453 debug("prolongecourbe : on a trouvé la valeur de i : "+str(i),liste_err)
454 if i>=len(ligne):
455 warning("prolongation de courbe : pas réussi... donnée trop haute !", liste_err)
456 return [],[]
457 if i==idep:
458 warning("prolongation de courbe : pas réussi... donnée trop basse !", liste_err)
459 return [],[]
460 liste_indices.append(i)
461 imin=min(liste_indices) -1
462 imax=max(liste_indices)
463 debug("Les données se situent dans les indices : "+str(imin)+", "+str(imax),liste_err)
464 # Maintenant on doit trouver les coeffs : on se situe en coeff * l[imin]+ (1-coeff)*ligne[imax]
465 # Et faire la moyenne de ces coeffs
466 total = 0
467 for k in range(len(dates)):
468 ligne = lignesoms[k]
469 donnee = donnees[k]
470 total += (donnee - ligne[imax])/(ligne[imin] - ligne[imax])
471 #print(k)
472 coeff_moyen = total/len(dates)
473
474 debug("Coeff moyen calculé : "+str(coeff_moyen), liste_err)
475
476 # On utilisera la même chose pour les nouvelle donnee
477
478 # extrapolations
479 nouvdates =oms.extraire_colonne(tableauOMS,0) # On sort tout.
480 #print(nouvdates)
481 nouvdonnees = []
482 for j in nouvdates:
483 ligne2 = tableauOMS[int(j)]
484 nouvdonnees.append(coeff_moyen*ligne2[imin]+ (1-coeff_moyen)*ligne2[imax])
485
486 return nouvdates,nouvdonnees
487
488
489 def dessine_guides(t, data, couleur, unite, ax, liste_err):
490 """ dessine deux lignes, horizontales et verticales qui vont "vers" la courbe
491 jusqu'aux points (t, data). En pointillés et avec un point dessus."""
492 debug("Début de dessine_guides"+str(t)+", "+str(data), liste_err)
493 t_conv = u.convertitunite(t,unite,liste_err)
494 ax.vlines(t_conv, 0, data, colors=couleur, linestyles="dashed")
495 ax.hlines(data, 0, t_conv, color=couleur, linestyles="dashed")
496 ax.plot([t_conv], [data], color=couleur, marker="*", ms=13)