]> git.immae.eu Git - perso/Denise/oms.git/blame - gestion_donnees.py
nouveauté : courbes multiples
[perso/Denise/oms.git] / gestion_donnees.py
CommitLineData
5679dfd0
DL
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
d03279e7 4from configuration import CONFIG,DEFAUT
a680b2f7
DL
5from gestion_erreurs import debug, warning, erreur, initialise_erreurs
6from gestion_couleurs import rgb_vers_tuple, tuple_vers_rgb
7from gestion_unites import choix_unite
5679dfd0 8import datetime
be2bf515
DL
9import json
10import unidecode
915e90bb 11import copy
5679dfd0 12
61020126
DL
13### Les données "tournent" selon :
14### python -> json -> (export/import) -> formulaire HTML -> données POST -> python etc
5679dfd0
DL
15
16############ Fonctions de conversion
17
18def convertit_jours_vers_python(chaine,liste_err):
19 """ convertit une chaine de type 1a 3m 1s 10j en jours
be2bf515 20 Renvoie un nombre de jours en float
5679dfd0
DL
21 Si un des caractères n'est ni un nombre, ni une lettre "autorisée" ni une espace,
22 on affiche un warning et on ignore ce caractère
23 """
b5ac625b 24# debug("conversion de "+chaine+" vers un nb de jours",liste_err)
5679dfd0
DL
25 chainenombre = ""
26 agejours = 0.
27 for lettre in chaine:
28 if lettre.isdigit():
29 chainenombre += lettre
30 else:
31 if lettre == 'a' or lettre == 'A':
32 # On a trouvé l'année, on ajoute tout ce qui est trouvé jusque là
d03279e7 33 agejours += int(chainenombre)*CONFIG["jours_dans_annee"]
5679dfd0
DL
34 chainenombre = ""
35 elif lettre == 'm' or lettre == 'M':
36 # On a trouvé le mois
d03279e7 37 agejours += int(chainenombre)*CONFIG["jours_dans_mois"]
5679dfd0
DL
38 chainenombre = ""
39 elif lettre == 's' or lettre == 'S':
40 # la semaine
d03279e7 41 agejours += int(chainenombre)*CONFIG["jours_dans_semaine"]
5679dfd0
DL
42 chainenombre = ""
43 elif lettre == 'j' or lettre == 'J':
44 # On a trouvé le jour
45 agejours += int(chainenombre)
46 chainenombre = ""
47 elif lettre != ' ':
48 # autre caractère : bizarre ?
49 warning("convertit_jour_vers_python : caractère invalide : "+lettre,liste_err)
50 # à la fin s'il reste qqch on le garde dans les jours
51 if chainenombre != "":
be2bf515 52 agejours += int(chainenombre)
5679dfd0
DL
53 if agejours<0:
54 warning("L'âge est négatif !",liste_err)
55 agejours = 0
b5ac625b 56# debug("On a convertit ! Résultat : "+str(agejours),liste_err)
be2bf515 57 return agejours
5679dfd0 58
8b5845ff 59# python -> json
5679dfd0
DL
60def convertit_age_vers_texte(nombre):
61 """ convertit un nombre de jours en un truc plus lisible en mois, années, jours
62 et renvoie une chaîne sous la forme 3a2m1j par exemple"""
d03279e7
DL
63 annees = int(nombre / CONFIG["jours_dans_annee"])
64 restant = nombre - annees*CONFIG["jours_dans_annee"]
65 mois = int(restant/CONFIG["jours_dans_mois"])
66 jours= round(nombre - mois*CONFIG["jours_dans_mois"] - annees*CONFIG["jours_dans_annee"])
5679dfd0
DL
67
68 chaine = ""
69 if annees >0:
70 chaine += str(annees)+"a"
71 if mois >0:
72 chaine += str(mois)+"m"
73 if jours>0 or nombre ==0: # si c'est la naissance, faut beien écrire 0j quand même
74 chaine += str(jours)+"j"
75 return chaine
a680b2f7 76
5679dfd0 77##########################
be2bf515 78
8b5845ff
DL
79# fonction qui calcule "auto" le maxi du graphique en fonction du max
80def calcule_max_graphique(l_jours):
81 """ calcule l'age maxi sur le graphique"""
82 if l_jours == []:
83 return CONFIG["jours_defaut_donneesvides"]
84 else:
85 jour_maxi = max(l_jours)# pas la peine d'aller très au delà du jour max
c2fe511b 86 jour_maxi = int(jour_maxi* 1.2)+3 # on rajoute un peu
8b5845ff
DL
87 return jour_maxi
88
be2bf515
DL
89
90def simplifie_nom(chaine):
91 """ simplifie le nom chaine afin d'en faire une extension
92 pour le nom du fichier. Met tout en minuscules et vire les caractères spéciaux
93 et max 15 caractères"""
94 chaine2 = ""
95 for l in chaine:
96 if l.isalpha():
97 chaine2+=l
98 chaine2 = unidecode.unidecode(chaine2)
99 return chaine2[:15]
5679dfd0 100
8b5845ff
DL
101def convertit_donnee_vers_python(chaine,typedonnee,liste_err):
102 """ convertit une chaine vers un float qui est le type donnee voulu.
103 La virgule peut être . ou , et on vire d'éventuels espaces.
ca61f310
DL
104 Taille invalide : on renvoie 0 avec un warning.
105 Si la chaine est en fait déjà au format float, on laisse tel quel"""
106 if type(chaine) == float:
107 return chaine
5679dfd0
DL
108 chaine2 = chaine.replace(",",".")
109 chaine2 = chaine2.replace(" ","")
ca61f310 110
5679dfd0
DL
111
112 try:
8b5845ff 113 donnee = float(chaine2)
5679dfd0 114 except:
8b5845ff
DL
115 warning(typedonnee+" impossible à lire : "+chaine,liste_err)
116 donnee = 0
d9eaf2e2
DL
117
118 # Pour le poids, un cas particulier
119 if typedonnee == "poids" and donnee > CONFIG["poids_maxi_conversion"]:
120 donnee = donnee/1000 # conversion en grammes
8b5845ff 121 if not( 0<=donnee<CONFIG[typedonnee+"_maxi"]):
d9eaf2e2 122 warning(typedonnee+" incohérent(e) : "+str(donnee),liste_err)
8b5845ff
DL
123 donnee = 0
124 return donnee
5679dfd0 125
5679dfd0
DL
126
127#########################
128
8b5845ff 129# web -> python
5679dfd0
DL
130def convertit_date_vers_python(chaine,liste_err):
131 """ prend une chaine comme renvoyée par un champ de formulaire date
132 aaaa-mm-jj et en fait une date python
133 renvoie "" si ne marche pas"""
134 liste = chaine.split("-")
135 if len(liste) != 3:
136 warning("La date : "+chaine+" est invalide !",liste_err)
137 return ""
138 else:
30158504 139 debug("Conversion de la date "+chaine+". Découpage : "+str(liste),liste_err)
9cb3c31c
DL
140 try:
141 date = datetime.date(int(liste[0]),int(liste[1]),int(liste[2]))
142 except:
143 date = ""
30158504 144 warning("Impossible de lire la date "+chaine+". Format accepté : aaaa-mm-jj",liste_err)
9cb3c31c 145 return date
8b5845ff
DL
146
147# python -> json
5679dfd0
DL
148def convertit_date_vers_texte(date):
149 """ convertit une date python en format texte aaaa-mm-jj"""
150 if date == "":
151 return ""
152 else:
153 return (str(date.year)+"-"+str(date.month)+"-"+str(date.day))
154
155
156def delta_date(date1,datenaissance):
157 """ renvoie le nombre de jours (entier) entre date1 et datenaissance format "datetime"
158 datenaissance est supposée antérieure. Erreur sinon."""
159 d = date1 - datenaissance
160 jours = d.days
161 if jours<0:
a680b2f7 162 warning("La différence entre les dates est négative... :/")
5679dfd0
DL
163 return -1
164 return jours
165
166
8b5845ff
DL
167################### On regroupe tout ce qui gère les données en une fonction
168
ca61f310 169def web_vers_python(data,liste_err, court=False):
8b5845ff 170 """ prend en argument le dictionnaire de requête et renvoie la config, et les
ca61f310
DL
171 tableaux de donnée
172 court : si True est précisé, on ne met que le nom dans la config (enfant
173 additionnel)"""
8b5845ff
DL
174
175 # Régler la configuration
ca61f310 176 config = gere_configuration(data,liste_err, court)
8b5845ff
DL
177
178 # récupérer les données
179 listes_jours = {}
180 listes_donnees = {}
181 for typed in CONFIG["liste_typedonnees"]:
182 listes_jours[typed],listes_donnees[typed] = gere_donnees(data,config["naissance"],typed,liste_err)
183
438ef56d
DL
184 # Si on veut extrapoler au-delà du jour maxi, on adapte
185
8b5845ff 186 # Si on a choisi la même échelle de données
ca61f310 187 if config.get("memechelle") == "oui":
8b5845ff 188 config["non_sauve"]["maxi"] = calcule_max_graphique([j for lj in listes_jours.values() for j in lj])
438ef56d
DL
189 # En cas d'extrapolation, on prend le maxi
190 if config["non_sauve"]["calculextradata_type"] !="" and config["non_sauve"]["calculextradata_age"]>config["non_sauve"]["maxi"]:
191 config["non_sauve"]["maxi"] = int(config["non_sauve"]["calculextradata_age"]) +1
8b5845ff
DL
192 config["non_sauve"]["unite"] = choix_unite(config["non_sauve"]["maxi"])
193
194 return (config,listes_jours,listes_donnees)
195
196
197
a680b2f7 198########### Fonctions qui gèretn les données web vers python
5679dfd0 199
8b5845ff
DL
200def gere_checkbox(chaine):
201 """ prend en arg une chaine, et renvoie "oui" si c'est "on" (sortie de la checkbox)
202 et chaîne vide si n'importe quoi d'autre"""
203 if chaine == "on":
204 return "oui"
205 else:
206 return ""
5679dfd0 207
ca61f310
DL
208def gere_symbole(chaine):
209 """ prend en arg une chaîne genre "o", ">" et vérifie si c'est un symbole valide.
210 Renvoie ce symbole-là ou le défaut"""
211 if chaine in CONFIG["liste_symboles"]:
212 return chaine
213 else:
214 return DEFAUT["symbole"]
215
216def gere_configuration(data,liste_err, court=False):
be2bf515 217 """ prend en argument le dictionnaire de requête (configuration imparfaite), et
5679dfd0 218 construit le dictionnaire de configuration qui va bien.
ca61f310
DL
219 Vérifie que chaque entrée est cohérente évidemment.
220 court : si mis à True, on ne met que le nom dans la configuraion,
221 ainsi que la date de naissance et le sexe"""
a680b2f7 222 # Initialisation
685a5f75 223 configuration = {"non_sauve": {}}
5679dfd0
DL
224
225 # Pour le nom, osef qu'il soit vide
226 nom = data.get("nom","")
227 # Par contre s'il est trop long on le tronque
d03279e7 228 configuration["nom"] = nom[:CONFIG["longueur_max_nom_bebe"]]
ca61f310 229
5679dfd0
DL
230 naissance = data.get("naissance","")
231 if naissance !="":
232 naissance = convertit_date_vers_python(naissance,liste_err)
233 configuration["naissance"] = naissance
234
ca61f310
DL
235 sexe = data.get("sexe","")
236 if not (sexe in ["F","M","N"]):
237 warning("Le sexe de l'enfant est invalide ! "+sexe,liste_err)
238 sexe = "N"
239 configuration["sexe"] = sexe
240
241 if not(court):
242
243 prematurite = data.get("prematurite","")
244 j = convertit_jours_vers_python(prematurite,liste_err)
245 configuration["prematurite"] = convertit_age_vers_texte(j)
5679dfd0 246
ca61f310
DL
247 configuration["agecorrige"] = gere_checkbox(data.get("agecorrige",""))
248
249 # Type de courbe. Au pire on met P
250 tyc = data.get("typecourbe","")
251 if not (tyc in ["P","Z"]):
252 tyc = "P"
253 configuration["typecourbe"] = tyc
254
255 # unité
256 unite = data.get("unite","")
257 if not (unite in CONFIG["liste_unites"]):
258 unite = ""
259 #warning("L'unité "+unite+" n'est pas reconnue !",liste_err)
260 configuration["unite"] = unite
261
262 # grille
263 configuration["grille"] = gere_checkbox(data.get("grille",""))
264
265 # tracer ou non les courbes vides
266 configuration["tracevide"] = gere_checkbox(data.get("tracevide",""))
267
268 # Même échelle sur tous les graphiques
269 configuration["memechelle"] = gere_checkbox(data.get("memechelle",""))
5679dfd0 270
ca61f310
DL
271
272 # maxi. 0 signifie qu'on veut pas de maxi
273 maxi = data.get("maxi","")
274 if maxi == "":
275 configuration["maxi"] = 0
276 else:
277 configuration["maxi"] = int(convertit_jours_vers_python(maxi,liste_err))
278
279 # dimensions du graphique
280 largeur = data.get("largeur","")
281 if largeur == "":
915e90bb 282 largeur = DEFAUT["largeur_graphique"]
ca61f310
DL
283 else:
284 try:
285 largeur = int(largeur)
286 except:
287 warning("La largeur "+largeur+"est invalide !",liste_err)
288 largeur = DEFAUT["largeur_graphique"]
289 if largeur > CONFIG["largeur_graphique_max"]:
290 largeur = CONFIG["largeur_graphique_max"]
291 warning("Largeur du graphique trop grande !",liste_err)
292 elif largeur < CONFIG["largeur_graphique_min"]:
293 largeur = CONFIG["largeur_graphique_min"]
294 warning("Largeur du graphique trop petite !",liste_err)
295 configuration["largeur"] = largeur
296
297 hauteur = data.get("hauteur","")
298 if hauteur == "":
915e90bb 299 hauteur = DEFAUT["hauteur_graphique"]
ca61f310
DL
300 else:
301 try:
302 hauteur = int(hauteur)
303 except:
304 warning("La hauteur "+hauteur+"est invalide !",liste_err)
305 hauteur = DEFAUT["hauteur_graphique"]
306 if hauteur > CONFIG["hauteur_graphique_max"]:
307 hauteur = CONFIG["hauteur_graphique_max"]
308 warning("Hauteur du graphique trop grande !",liste_err)
309 elif hauteur < CONFIG["hauteur_graphique_min"]:
310 hauteur = CONFIG["hauteur_graphique_min"]
311 warning("Hauteur du graphique trop petite !",liste_err)
312 configuration["hauteur"] = hauteur
313
314 # existence et position de la légende
315 configuration["legende"] = gere_checkbox(data.get("legende",""))
316
317 positionlegende = data.get("positionlegende","")
318 if not(positionlegende in ['upper left','upper right','lower left','lower right']):
319 positionlegende = "upper left"
320 configuration["positionlegende"] = positionlegende
321
322 configuration["couleurs"] = {}
323 # gérer les couleurs
324 for clecouleur in DEFAUT["couleurs"]:
325 coul = rgb_vers_tuple(data.get("couleur_"+clecouleur,""),CONFIG["couleurs"][clecouleur],liste_err)
326 configuration["couleurs"][clecouleur] = coul
327
328 # symbole
329 configuration["symbole"] = gere_symbole( data.get("symbole", ""))
fd69b6b5 330
ca61f310 331 configuration["non_sauve"]["grilleamelio"] = gere_checkbox(data.get("grilleamelio",""))
cf0d4c8c 332
cf0d4c8c 333
ca61f310
DL
334 #### La partie extrapolation n'a pas besoin d'être sauvée
335 configuration["non_sauve"]["prolongercourbes"] = gere_checkbox(data.get("prolongercourbes",""))
fd69b6b5 336
ca61f310
DL
337 # Valeur par défaut : 1
338 debug(data.get("nbextradata", "aaargh"), liste_err)
339 nbextradata = data.get("nbextradata",1)
340 try:
341 nbextradata = int(nbextradata)
342 except:
343 warning("Le nombre de données sur lequel on extrapole est invalide : "+nbextradata, liste_err)
344 nbextradata = 1
345 configuration["non_sauve"]["nbextradata"] = nbextradata
346
347 if data.get("calculextradata_type","") in CONFIG["liste_typedonnees"]:
348 configuration["non_sauve"]["calculextradata_type"] = data.get("calculextradata_type","")
349 configuration["non_sauve"]["calculextradata_age"] = convertit_jours_vers_python(data.get("calculextradata_age","0j"),liste_err)
350 else:
351 configuration["non_sauve"]["calculextradata_type"] = ""
352 # On ne met rien dans l'âge, pas la peine
353
354 ctyped = data.get("calculextratemps_type","")
355 if ctyped in CONFIG["liste_typedonnees"]:
356 configuration["non_sauve"]["calculextratemps_type"] = ctyped
357 configuration["non_sauve"]["calculextratemps_val"] = convertit_donnee_vers_python(data.get("calculextratemps_val",""), ctyped, liste_err)
358 else:
359 configuration["non_sauve"]["calculextratemps_type"] = ""
360
361 # Tracer les calculs sur la grille
362 configuration["non_sauve"]["calculextradata_trace"] = gere_checkbox(data.get("calculextradata_trace"))
363 configuration["non_sauve"]["calculextratemps_trace"] = gere_checkbox(data.get("calculextratemps_trace"))
3d7da80a
DL
364
365
5679dfd0 366 return configuration
5679dfd0 367
cf0d4c8c
DL
368
369
a680b2f7 370## web vers python : données
8b5845ff
DL
371def gere_donnees(data,naissance,typedonnee,liste_err):
372 """ prend en argument le dictionnaire de requête, et la date de
373 naissance (éventuellement vide), et construit deux listes :
374 l_jours et l_data correspondantes.
375 Il faut donner en argument le type de données : voir
376 CONFIG["liste_typedonnees"]"""
377 if typedonnee not in CONFIG["liste_typedonnees"]:
378 warning("gere_donnees : le type de données : "+typedonnee+" est invalide !! Types acceptés : "+str(CONFIG["liste_typedonnees"]),liste_err)
379 return ([],[])
380
381 # On construit une liste de couples d'abord
5679dfd0
DL
382 liste_donnees = []
383
384 i = 0
8b5845ff
DL
385 # On va chercher si y'a des données à donnee_i
386 while typedonnee+"_"+str(i) in data.keys():
387 if data[typedonnee+"_"+str(i)] != "":
388 donnee = convertit_donnee_vers_python(data[typedonnee+"_"+str(i)],typedonnee,liste_err)
5679dfd0
DL
389 age = data.get("age_"+str(i),"")
390 if age !="":
391 age = convertit_jours_vers_python(age,liste_err)
8b5845ff 392 liste_donnees.append((age,donnee))
5679dfd0
DL
393 else:
394 date = data.get("date_"+str(i),"")
395 datep = convertit_date_vers_python(date,liste_err)
396 # on vérifie la date
397 if naissance == "":
398 warning("La date de naissance n'a pas été précisée. Du coup on ne peut pas calculer l'âge de l'enfant le "+date,liste_err)
399 elif datep != "": # la date est valide et on a une date de naissance
400 age = delta_date(datep,naissance)
8b5845ff 401 liste_donnees.append((age,donnee))
5679dfd0
DL
402 i+=1
403
404 # Trier la liste
405 liste_donnees.sort(key=lambda x : x[0])
406
407 # splitter la liste
408 l_jours = [x[0] for x in liste_donnees]
8b5845ff 409 l_donnee = [x[1] for x in liste_donnees]
5679dfd0 410
8b5845ff 411 return (l_jours,l_donnee)
be2bf515
DL
412
413
a680b2f7 414# python vers Json
8b5845ff 415#### export vers json
be2bf515 416
8b5845ff 417def donnees_vers_json(l_jours,l_poids,l_jourst,l_taille,config):
be2bf515 418 """ retourne le json à renvoyer"""
915e90bb 419 gros_dico = copy.deepcopy(config)
be2bf515 420 l_jours2 = [convertit_age_vers_texte(d) for d in l_jours]
8b5845ff 421 l_jourst2 = [convertit_age_vers_texte(d) for d in l_jourst]
be2bf515
DL
422 gros_dico["data_j"] = l_jours2
423 gros_dico["data_p"] = l_poids
8b5845ff
DL
424 gros_dico["data_jours_taille"] = l_jourst2
425 gros_dico["data_taille"] = l_taille
be2bf515
DL
426 # gérer la date de naissance
427 if gros_dico.get("naissance","") != "":
428 gros_dico["naissance"] = convertit_date_vers_texte(gros_dico["naissance"])
429 # gérer l'age maxi
430 gros_dico["maxi"] = convertit_age_vers_texte(gros_dico["maxi"])
fd69b6b5 431 # gérer les couleurs
915e90bb
DL
432 for clecouleur in DEFAUT["couleurs"]:
433 gros_dico["couleurs"][clecouleur] = tuple_vers_rgb(gros_dico["couleurs"][clecouleur])
fd69b6b5 434
8b5845ff
DL
435 # Enlever ce qui ne se sauvegarde pas si y'a
436 if "non_sauve" in gros_dico:
437 del gros_dico["non_sauve"]
5679dfd0 438
be2bf515 439 return json.dumps(gros_dico, indent=2,ensure_ascii=False )
5679dfd0 440
8b5845ff
DL
441def fusionne_donnees(listes_jours,listes_donnees):
442 """ prend en argument deux dicos de listes. Chaque liste de jours est associée à une liste
443 de données (par la même clé de type de données). Il faut les fusionner pour avoir une liste de dictionnaires, de type
444 ("age":truc, "donnee1":truc, "donnee2":truc, ...) triée par ordre de jours. Si jamais une des données est vide,
445 le champ du dictionnaire n'est pas rempli"""
a680b2f7 446
8b5845ff
DL
447 def fini(lj):
448 """ teste si les listes sont toutes vides """
449 for l in lj.values():
450 if l!=[]:
451 return False
452 return True
453
454 def mini(lj):
455 """ renvoie la clé de la liste où il y a le min """
456 cle_mini = CONFIG["liste_typedonnees"][0]
457 for (cle,liste) in lj.items():
458 if lj[cle_mini]== []:
459 cle_mini = cle
460 elif lj[cle] != []:
b5ac625b 461 if convertit_jours_vers_python(lj[cle][0],initialise_erreurs())<convertit_jours_vers_python(lj[cle_mini][0],initialise_erreurs()):
8b5845ff
DL
462 cle_mini = cle
463 return cle_mini
464
465 liste_f = []
466 while not(fini(listes_jours)):
467 typedonnee = mini(listes_jours)
468 # On extrait les données dans les deux listes (jours et données)
469 jour = listes_jours[typedonnee].pop(0)
470 donnee = listes_donnees[typedonnee].pop(0)
471 if liste_f == [] or jour != liste_f[-1]["age"]: # Si le jour est un "nouveau" jour
472 liste_f.append({"age":jour})
473 # On met à jour l'élément
474 liste_f[-1][typedonnee] = donnee
475
476 return liste_f
477
5679dfd0 478
a680b2f7 479### COnversion json vers formulaire
8b5845ff 480# Json -> formulaire HTML
d03279e7 481def fichier_json_vers_configdonnees(chaine,liste_err):
a680b2f7
DL
482 """ prend le json importé (chaine) et l'exporte vers les valeurs du formulaire
483 Renvoyé sous forme de dictionnaire (mais adapté au formulaire web)"""
d03279e7
DL
484 debug("json vers config : Prêt à interpréter le json",liste_err)
485 try:
486 valform = json.loads(chaine)
487 except :
488 erreur("Impossible de lire le fichier json !",liste_err)
489 return {}
be2bf515
DL
490 # Il faut maintenant récupérer les l_jours et l_poids puis les remettre
491 # sous forme de age_i et poids_i
8b5845ff
DL
492
493 listes_jours = {}
494 listes_donnees = {}
495 for typed in CONFIG["liste_typedonnees"]:
496 if typed == "poids": # pour la rétrocompatibilité
497 listes_jours[typed] = valform.get("data_j",[])
498 listes_donnees[typed] = valform.get("data_p",[])
499 else:
500 listes_jours[typed] = valform.get("data_jours_"+typed,[])
501 listes_donnees[typed] = valform.get("data_"+typed,[])
502
503 debug("Avant fusion : listes jours "+str(listes_jours),liste_err)
504 liste_donnees = fusionne_donnees(listes_jours,listes_donnees)
505 debug("Fusion de listes ok. Liste moche : "+str(liste_donnees),liste_err)
506 for i in range(len(liste_donnees)):
507 for (cle,val) in liste_donnees[i].items():
508 valform[cle+"_"+str(i)] = val
be2bf515 509
8b5845ff 510 valform["nb_data"] = max(len(liste_donnees) +2,DEFAUT["nb_data"])
5679dfd0 511
be2bf515 512 return valform
5679dfd0 513
5679dfd0 514
ca61f310
DL
515
516#### Pour l'insertion d'une 2e (ou plus) courbe sur le graphique, ue fonction qui sépare tout ça
517def eclate_donnees_additionnelles(conf, ljours, ldonnees, symb):
518 """ conf est la config (on ne garde que le nom) pour un enfant additionnel,
519 ljours et ldonnees les dictionnaires de listes contenant les données.
520 symb est le symbole choisi pour cette courbe additionnelle (déjà vérifié)
521 On fabrique un joli dictionnaire typed -> (conf lj, ldonnee) avec le nom de l'enfant,
522 et les données pour chaque typed"""
523
524 retour = {}
525 conf["symbole"] = symb # On ajoute le symbole additionnel
526 for typed in CONFIG["liste_typedonnees"]:
527 retour[typed] = (conf, ljours[typed], ldonnees[typed])
528
529 return retour