summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenise sur Lya <sekhmet@lya>2021-02-18 20:05:29 +0100
committerDenise sur Lya <sekhmet@lya>2021-02-18 20:05:29 +0100
commitcf0d4c8c36224ca7059e99d03c25abaf694011d7 (patch)
tree2d1642c8576ee5d07dee33b399fae6ef05022b87
parenta680b2f78891692be215013481e167da2fffb5d8 (diff)
downloadoms-cf0d4c8c36224ca7059e99d03c25abaf694011d7.tar.gz
oms-cf0d4c8c36224ca7059e99d03c25abaf694011d7.tar.zst
oms-cf0d4c8c36224ca7059e99d03c25abaf694011d7.zip
extrapolation des courbes et calculs associés
-rw-r--r--app.py38
-rw-r--r--calculs_extrapole.py89
-rw-r--r--configuration.py4
-rw-r--r--data/changelog_data.txt2
-rw-r--r--gestionOMS.py4
-rw-r--r--gestion_donnees.py37
-rw-r--r--gestion_unites.py17
-rw-r--r--static/requetes.js15
-rw-r--r--static/style.css11
-rw-r--r--templates/base.html8
-rw-r--r--templates/index.html41
-rw-r--r--trace_courbe.py156
12 files changed, 354 insertions, 68 deletions
diff --git a/app.py b/app.py
index 02d88c4..958efd5 100644
--- a/app.py
+++ b/app.py
@@ -14,10 +14,23 @@ from trace_courbe import cree_figure
14import faq as f 14import faq as f
15 15
16 16
17def initialise_mode_beta():
18 global beta
19 hote = flask.request.host
20 if hote[:4] == "beta":
21 print("** Mode bêta !**")
22 return True
23 else:
24 return False
25
26
17app = flask.Flask(__name__) 27app = flask.Flask(__name__)
18 28
29
30
19@app.route('/',methods=['POST','GET']) 31@app.route('/',methods=['POST','GET'])
20def index(): 32def index():
33 beta=initialise_mode_beta()
21 liste_err = initialise_erreurs() 34 liste_err = initialise_erreurs()
22 val_form = config_init() 35 val_form = config_init()
23 if flask.request.method=="POST": 36 if flask.request.method=="POST":
@@ -29,13 +42,13 @@ def index():
29 if val_form2 == {}: 42 if val_form2 == {}:
30 return flask.render_template("index.html",err=liste_err[2]+liste_err[1]+liste_err[0],valform=val_form) 43 return flask.render_template("index.html",err=liste_err[2]+liste_err[1]+liste_err[0],valform=val_form)
31 val_form.update(val_form2) 44 val_form.update(val_form2)
32 #return str(val_form['nb_data']) 45
33 return flask.render_template("index.html",err=liste_err[1],valform=val_form) 46 return flask.render_template("index.html",err=liste_err[1],valform=val_form, CONFIG=CONFIG, beta=beta)
34 47
35@app.route('/apropos') 48@app.route('/apropos')
36def apropos(): 49def apropos():
37 50 beta=initialise_mode_beta()
38 return flask.render_template("apropos.html",err=[]) 51 return flask.render_template("apropos.html",err=[], beta=beta)
39 52
40 53
41@app.route("/courbe/<ext>", methods=['POST']) 54@app.route("/courbe/<ext>", methods=['POST'])
@@ -58,10 +71,11 @@ def courbe_image(ext):
58 try: 71 try:
59 debug("création des figures...",liste_err) 72 debug("création des figures...",liste_err)
60 textes_images = {} 73 textes_images = {}
74 liste_extracalculs = []
61 for typed in CONFIG["liste_typedonnees"]: 75 for typed in CONFIG["liste_typedonnees"]:
62 if config["tracevide"] == "oui" or listes_jours[typed] != []: 76 if config["tracevide"] == "oui" or listes_jours[typed] != []:
63 debug("On trace la courbe de "+typed,liste_err) 77 debug("On trace la courbe de "+typed,liste_err)
64 fig = cree_figure(config,listes_jours[typed],listes_donnees[typed],typed,liste_err) 78 fig = cree_figure(config,listes_jours[typed],listes_donnees[typed],typed,liste_extracalculs, liste_err)
65 output = io.BytesIO() 79 output = io.BytesIO()
66 FigureCanvas(fig).print_png(output) 80 FigureCanvas(fig).print_png(output)
67 plt.close(fig) 81 plt.close(fig)
@@ -80,13 +94,16 @@ def courbe_image(ext):
80 "export_txt": texte, 94 "export_txt": texte,
81 "nomenfant": nomenfant} 95 "nomenfant": nomenfant}
82 if result == "success": 96 if result == "success":
83 reponse["messages"] = liste_err[0] 97 reponse["messages"] = liste_err[0]+liste_err[1]
98 reponse["calculextra"] = liste_extracalculs
84 else: 99 else:
85 reponse["messages"] = liste_err[2]+liste_err[1]+liste_err[0] 100 reponse["messages"] = liste_err[2]+liste_err[1]+liste_err[0]
86 101
87 for typed in CONFIG["liste_typedonnees"]: 102 for typed in CONFIG["liste_typedonnees"]:
88 reponse["image_"+typed] = textes_images.get(typed,"") 103 reponse["image_"+typed] = textes_images.get(typed,"")
89 104
105
106
90 return flask.jsonify(reponse) 107 return flask.jsonify(reponse)
91 elif ext == "png" and result == "success": # à voir cette partie car il faudrait voir ce qu'on y renvoie... vu 108 elif ext == "png" and result == "success": # à voir cette partie car il faudrait voir ce qu'on y renvoie... vu
92 # qu'il n'y a plus une courbe mais plusieurs. Là ça renverra la dernière générée. 109 # qu'il n'y a plus une courbe mais plusieurs. Là ça renverra la dernière générée.
@@ -99,22 +116,25 @@ def courbe_image(ext):
99 116
100@app.route("/contact") 117@app.route("/contact")
101def contact(): 118def contact():
102 return flask.render_template("contact.html",err=[]) 119 beta=initialise_mode_beta()
120 return flask.render_template("contact.html",err=[], beta=beta)
103 121
104@app.route("/faq") 122@app.route("/faq")
105def faq(): 123def faq():
124 beta=initialise_mode_beta()
106 125
107 table_faq = f.lire_fichier_csv_simple(f.fichier_FAQ) 126 table_faq = f.lire_fichier_csv_simple(f.fichier_FAQ)
108 l_categ,table_qr = f.extraire_tables_par_cat(table_faq) 127 l_categ,table_qr = f.extraire_tables_par_cat(table_faq)
109 128
110 return flask.render_template("faq.html",lcateg=l_categ,tableqr=table_qr,err=[]) 129 return flask.render_template("faq.html",lcateg=l_categ,tableqr=table_qr,err=[], beta=beta)
111 130
112@app.route("/changelog") 131@app.route("/changelog")
113def changelog(): 132def changelog():
133 beta=initialise_mode_beta()
114 134
115 table_version = f.lire_fichier_csv_simple(f.fichier_changelog) 135 table_version = f.lire_fichier_csv_simple(f.fichier_changelog)
116 136
117 return flask.render_template("changelog.html",table = table_version,err=[]) 137 return flask.render_template("changelog.html",table = table_version,err=[], beta=beta)
118 138
119if __name__ == "__main__": 139if __name__ == "__main__":
120 print("Mode debug maison : "+str(niveau_debug)) 140 print("Mode debug maison : "+str(niveau_debug))
diff --git a/calculs_extrapole.py b/calculs_extrapole.py
new file mode 100644
index 0000000..ab22502
--- /dev/null
+++ b/calculs_extrapole.py
@@ -0,0 +1,89 @@
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4Created on Thu Feb 18 18:25:11 2021
5
6@author: sekhmet
7"""
8
9from gestion_erreurs import warning, debug
10from configuration import CONFIG
11from gestion_donnees import convertit_age_vers_texte
12import gestion_unites as u
13
14#### Les fonctions qui permettent de faire les calculs additionnels une fois qu'on a l'extrapolation
15
16def met_s(chaine):
17 """ renvoie un s si pluriel, rien sinon"""
18 if int(chaine)>1:
19 return "s"
20 else:
21 return ""
22
23def joliechaine_age(age):
24 """ prend en argument une chaîne du type 6a3m2j et renvoie une chaîne un peu
25 plus jolie à lire genre 6 ans, 3mois, 2 jours"""
26 retour = ""
27 nombre = ""
28 for char in age:
29 if char=="a":
30 retour+=nombre+" année"+met_s(nombre)+", "
31 nombre=""
32 elif char=="m":
33 retour+=nombre+" mois, "
34 nombre=""
35 elif char=="s":
36 retour+=nombre+" semaine"+met_s(nombre)+", "
37 nombre=""
38 elif char=="j":
39 retour+=nombre+" jour"+met_s(nombre)+", "
40 nombre=""
41 else:
42 nombre+=char
43 #print(retour)
44 return retour[:-2]
45
46
47
48def calcule_donnee_extrapolee(dates_extrapole, donnees_extrapole, age_voulu, typedonnee, liste_err):
49 """ prend en argument les données extrapolées, l'âge voulu en jours,
50 et le type de données qu'on veut afficher, et renvoie une jolie phrase
51 à afficher"""
52 age_voulu = int(age_voulu) # pour avoir les choses bien
53 debug("On veut la donnée à l'âge "+str(age_voulu), liste_err)
54 try:
55 i_date_voulue = dates_extrapole.index(age_voulu)
56 donnee_voulue = donnees_extrapole[i_date_voulue]
57 donnee_arrondie = u.arrondit_donnee(donnee_voulue, typedonnee)
58 chaine = "À "+joliechaine_age(convertit_age_vers_texte(age_voulu))
59
60 if typedonnee == "poids":
61 return chaine+", l'enfant pèsera "+str(donnee_arrondie)+" kg."
62 elif typedonnee == "taille":
63 return chaine+", l'enfant mesurera "+str(donnee_arrondie)+" cm."
64 else: # phrase générique
65 return chaine+", la donnée sera : "+str(donnee_arrondie)+" "+CONFIG["unites_typedonnees"][typedonnee]+"."
66 except:
67 warning("Impossible de calculer la donnée à l'âge "+age_voulu, liste_err)
68 return ""
69
70def calcule_age_extrapole(dates_extrapole, donnees_extrapole, donnee_voulue, typedonnee, liste_err):
71 """ prend en argument les données extrapolées, la donnée voulue (dans l'unité adaptée)
72 et son type, et renvoie la jolie phrase à afficher"""
73
74 debug("On veut savoir à quel âge on a "+str(donnee_voulue), liste_err)
75 try:
76 i=0
77 while i<len(donnees_extrapole) and donnees_extrapole[i]<donnee_voulue:
78 i+=1
79
80 age_joli = joliechaine_age(convertit_age_vers_texte(dates_extrapole[i]))
81 if typedonnee=="poids":
82 return "L'enfant atteindra un poids de "+str(donnee_voulue)+" kg à l'âge de "+age_joli+"."
83 elif typedonnee=="taille":
84 return "L'enfant atteindra la taille "+str(donnee_voulue)+ "cm à l'âge de "+age_joli+"."
85 else:# phrase générique
86 return "L'enfant atteindra la donnée "+typedonnee+" "+str(donnee_voulue)+" à l'âge de "+age_joli+"."
87 except:
88 warning("Impossible de calculer l'âge pour la donnée "+str(donnee_voulue), liste_err)
89 return ""
diff --git a/configuration.py b/configuration.py
index fd6df9e..5e0ec81 100644
--- a/configuration.py
+++ b/configuration.py
@@ -8,7 +8,11 @@ CONFIG = {}
8CONFIG["liste_unites"] = ["jours", "semaines", "mois", "années"] 8CONFIG["liste_unites"] = ["jours", "semaines", "mois", "années"]
9CONFIG["liste_typedonnees"] = ["poids","taille"] 9CONFIG["liste_typedonnees"] = ["poids","taille"]
10CONFIG["unites_typedonnees"] = {"poids": "kg", "taille":"cm"} 10CONFIG["unites_typedonnees"] = {"poids": "kg", "taille":"cm"}
11# à combien on arrondit par défaut les dnnées
12CONFIG["arrondis_typedonnees"] = {"poids": 0.01, "taille": 1}
11 13
14# Liste des calculs additionnels
15CONFIG["extradata"] = ["calculextradata", "calculextratemps"]
12 16
13# fichiers 17# fichiers
14 18
diff --git a/data/changelog_data.txt b/data/changelog_data.txt
index f0b26b0..c220b15 100644
--- a/data/changelog_data.txt
+++ b/data/changelog_data.txt
@@ -1,3 +1,5 @@
1"Version 2.5","18/02/2021","<p>Nouveauté : extrapolation de la courbe améliorée et calculs possibles ! En bêta, à tester !</p>"
2
1"Version 2.261","16/02/2021","<p>Du mieux sur la gestion de la grille améliorée, qui passe en ""par défaut"" maintenant. Plus une correction de bug sur l'échelle du graphique, et du code nettoyé. On dirait pas comme ça, hein ? N'hésitez pas à me signaler tout vilain bug persistant !</p>" 3"Version 2.261","16/02/2021","<p>Du mieux sur la gestion de la grille améliorée, qui passe en ""par défaut"" maintenant. Plus une correction de bug sur l'échelle du graphique, et du code nettoyé. On dirait pas comme ça, hein ? N'hésitez pas à me signaler tout vilain bug persistant !</p>"
2 4
3"Version 2.26","15/02/2021","<p>Nouveauté en bêta-test : grille améliorée. Pour le moment on peut cocher pour avoir cette fonctionnalité.</p>" 5"Version 2.26","15/02/2021","<p>Nouveauté en bêta-test : grille améliorée. Pour le moment on peut cocher pour avoir cette fonctionnalité.</p>"
diff --git a/gestionOMS.py b/gestionOMS.py
index b00b93b..8c2b910 100644
--- a/gestionOMS.py
+++ b/gestionOMS.py
@@ -81,9 +81,11 @@ def lire_fichier_csv(fichier):
81 return table 81 return table
82 82
83 83
84def extraire_colonne(table,ncol,maxi): 84def extraire_colonne(table,ncol,maxi=-1):
85 """ extrait une colonne d'un tableau double, de taille maximum maxi""" 85 """ extrait une colonne d'un tableau double, de taille maximum maxi"""
86 t = [] 86 t = []
87 if maxi==-1:
88 maxi = len(table)
87 for i in range( min(len(table),maxi) ): 89 for i in range( min(len(table),maxi) ):
88 t.append(table[i][ncol]) 90 t.append(table[i][ncol])
89 return t 91 return t
diff --git a/gestion_donnees.py b/gestion_donnees.py
index 169f3da..123120b 100644
--- a/gestion_donnees.py
+++ b/gestion_donnees.py
@@ -291,11 +291,6 @@ def gere_configuration(data,liste_err):
291 if not(positionlegende in ['upper left','upper right','lower left','lower right']): 291 if not(positionlegende in ['upper left','upper right','lower left','lower right']):
292 positionlegende = "upper left" 292 positionlegende = "upper left"
293 configuration["positionlegende"] = positionlegende 293 configuration["positionlegende"] = positionlegende
294
295 configuration["prolongercourbes"] = gere_checkbox(data.get("prolongercourbes",""))
296
297 # Ceci n'a pas besoin d'être sauvé
298 configuration["non_sauve"]["grilleamelio"] = gere_checkbox(data.get("grilleamelio",""))
299 294
300 configuration["couleurs"] = {} 295 configuration["couleurs"] = {}
301 # gérer les couleurs 296 # gérer les couleurs
@@ -303,9 +298,41 @@ def gere_configuration(data,liste_err):
303 coul = rgb_vers_tuple(data.get("couleur_"+clecouleur,""),CONFIG["couleurs"][clecouleur],liste_err) 298 coul = rgb_vers_tuple(data.get("couleur_"+clecouleur,""),CONFIG["couleurs"][clecouleur],liste_err)
304 configuration["couleurs"][clecouleur] = coul 299 configuration["couleurs"][clecouleur] = coul
305 300
301
302 configuration["non_sauve"]["grilleamelio"] = gere_checkbox(data.get("grilleamelio",""))
303
304
305 #### La partie extrapolation n'a pas besoin d'être sauvée
306 configuration["non_sauve"]["prolongercourbes"] = gere_checkbox(data.get("prolongercourbes",""))
307
308 # Valeur par défaut : 1
309 debug(data.get("nbextradata", "aaargh"), liste_err)
310 nbextradata = data.get("nbextradata",1)
311 try:
312 nbextradata = int(nbextradata)
313 except:
314 warning("Le nombre de données sur lequel on extrapole est invalide : "+nbextradata, liste_err)
315 nbextradata = 1
316 configuration["non_sauve"]["nbextradata"] = nbextradata
317
318 if data.get("calculextradata_type","") in CONFIG["liste_typedonnees"]:
319 configuration["non_sauve"]["calculextradata_type"] = data.get("calculextradata_type","")
320 configuration["non_sauve"]["calculextradata_age"] = convertit_jours_vers_python(data.get("calculextradata_age","0j"),liste_err)
321 else:
322 configuration["non_sauve"]["calculextradata_type"] = ""
323 # On ne met rien dans l'âge, pas la peine
324
325 ctyped = data.get("calculextratemps_type","")
326 if ctyped in CONFIG["liste_typedonnees"]:
327 configuration["non_sauve"]["calculextratemps_type"] = ctyped
328 configuration["non_sauve"]["calculextratemps_val"] = convertit_donnee_vers_python(data.get("calculextratemps_val",""), ctyped, liste_err)
329 else:
330 configuration["non_sauve"]["calculextratemps_type"] = ""
306 331
307 return configuration 332 return configuration
308 333
334
335
309## web vers python : données 336## web vers python : données
310def gere_donnees(data,naissance,typedonnee,liste_err): 337def gere_donnees(data,naissance,typedonnee,liste_err):
311 """ prend en argument le dictionnaire de requête, et la date de 338 """ prend en argument le dictionnaire de requête, et la date de
diff --git a/gestion_unites.py b/gestion_unites.py
index d4089bd..f4cc38e 100644
--- a/gestion_unites.py
+++ b/gestion_unites.py
@@ -3,6 +3,7 @@
3 3
4from configuration import CONFIG 4from configuration import CONFIG
5from gestion_erreurs import warning 5from gestion_erreurs import warning
6from math import log
6 7
7##################### outils pour affichage et choix de l'unité 8##################### outils pour affichage et choix de l'unité
8 9
@@ -94,4 +95,18 @@ def convertitunite(jours,unite,liste_err):
94def convertit_tableau(tableau,unite,liste_err): 95def convertit_tableau(tableau,unite,liste_err):
95 """ convertit un tableau de jours en une autre unité. 96 """ convertit un tableau de jours en une autre unité.
96 Renvoie le nouveau tableau""" 97 Renvoie le nouveau tableau"""
97 return [convertitunite(elt,unite,liste_err) for elt in tableau] \ No newline at end of file 98 return [convertitunite(elt,unite,liste_err) for elt in tableau]
99
100def arrondit_donnee(donnee, typed, arrondi=0):
101 """ on arrondit la donnée de type typed (à voir dans CONFIG)
102 à arrondit près. SI y'a 0 on va voir dans la config.
103 Pour l'arrondit on met par ex 1 pour arrondir à 1 pr_s, 0.1 pour arrondir
104 au dixième etc"""
105 if arrondi==0:
106 arrondi = CONFIG["arrondis_typedonnees"][typed]
107 if arrondi==0:
108 print("Euuuh ça va merder, y'a une div par 0 dans arrondit_donnees !")
109
110 d_arr = round(donnee/arrondi)*arrondi
111 nbchiffresvoulus = int(log(1/arrondi, 10))+1 # max sur le nombre de chiffres après la virgule qu'on doit avoir
112 return round(d_arr, nbchiffresvoulus) \ No newline at end of file
diff --git a/static/requetes.js b/static/requetes.js
index 57330b3..6228020 100644
--- a/static/requetes.js
+++ b/static/requetes.js
@@ -19,6 +19,7 @@ function appelle_image()
19 var liste_warnings = this.response.messages 19 var liste_warnings = this.response.messages
20 var texte = this.response.export_txt; 20 var texte = this.response.export_txt;
21 var nomenfant = this.response.nomenfant ; 21 var nomenfant = this.response.nomenfant ;
22 var calculextra = this.response.calculextra ;
22 23
23 // on affiche l'export des données 24 // on affiche l'export des données
24 document.getElementById('export').innerHTML = texte; 25 document.getElementById('export').innerHTML = texte;
@@ -67,7 +68,19 @@ function appelle_image()
67 li.appendChild(document.createTextNode(liste_warnings[i])); 68 li.appendChild(document.createTextNode(liste_warnings[i]));
68 ul.appendChild(li); 69 ul.appendChild(li);
69 } 70 }
70 } 71 }
72 // S'il y a des calculs faits, à afficher !
73 if(calculextra.length != 0)
74 {
75 var elem_extr = document.getElementById("section_extradonnees")
76 elem_extr.style.display = "block" ;
77 var ul2=elem_extr.children[1] ;
78 for(i=0; i<calculextra.length; i++) {
79 var li = document.createElement("li");
80 li.appendChild(document.createTextNode(calculextra[i]));
81 ul2.appendChild(li);
82 }
83 }
71 } 84 }
72 else{ // si la génération de l'image a merdé 85 else{ // si la génération de l'image a merdé
73 86
diff --git a/static/style.css b/static/style.css
index 667bc01..2c2358e 100644
--- a/static/style.css
+++ b/static/style.css
@@ -10,6 +10,13 @@ h1 {
10 text-align: center; 10 text-align: center;
11} 11}
12 12
13.bandeau_beta {
14 background: #F5BF62;
15 border-style: solid;
16 border-width: 3px ;
17 padding: 0px 5px ;
18}
19
13#warnings { 20#warnings {
14 background: #ff8060; 21 background: #ff8060;
15} 22}
@@ -22,7 +29,7 @@ img#courbe {
22 max-width: 100% 29 max-width: 100%
23} 30}
24 31
25#sectioncourbe, #section_courbe_poids, #section_courbe_taille { 32#sectioncourbe, #section_courbe_poids, #section_courbe_taille, #section_extradonnees {
26 display: none; 33 display: none;
27} 34}
28 35
@@ -45,7 +52,7 @@ img#courbe {
45 display: none; 52 display: none;
46} 53}
47 54
48#pref_graphique { 55#pref_graphique, #extra {
49 display: none; 56 display: none;
50} 57}
51 58
diff --git a/templates/base.html b/templates/base.html
index dd4192a..53512d9 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -24,6 +24,13 @@
24 </div> 24 </div>
25 {% endif %} 25 {% endif %}
26 26
27 {% if beta %}
28 <div class="bandeau_beta">
29 <p>Attention !</p>
30 </p>Ceci est la version « Bêta-test » du site. Il se peut que l'outil ait un comportement inattendu ou buggue. Si vous ne savez pas ce que vous
31 faites là, retournez sur le site normal <a href="https://oms.syanni.eu">en cliquant ici</a></p>
32 </div>
33 {% endif %}
27 34
28 <div id="content"> 35 <div id="content">
29 {% block contenu %}{% endblock %} 36 {% block contenu %}{% endblock %}
@@ -37,7 +44,6 @@
37 <a href="/contact">Contact</a> | 44 <a href="/contact">Contact</a> |
38 <a href="/apropos">À propos</a> | 45 <a href="/apropos">À propos</a> |
39 <a href="/changelog">Changelog</a> 46 <a href="/changelog">Changelog</a>
40
41 </nav> 47 </nav>
42 48
43 </body> 49 </body>
diff --git a/templates/index.html b/templates/index.html
index 34be454..91230f4 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -39,7 +39,7 @@
39 <p id="changemode" class="petit"><span onclick="change_mode_dates('text')" class="bouton">Cliquer ici</span> pour saisir les dates comme du texte.</p> </li> 39 <p id="changemode" class="petit"><span onclick="change_mode_dates('text')" class="bouton">Cliquer ici</span> pour saisir les dates comme du texte.</p> </li>
40<li>Prématuré ? <span class="petit">(expérimental)</span> <span class="bouton" onclick="affiche_cache('prema',this)">Afficher</span> 40<li>Prématuré ? <span class="petit">(expérimental)</span> <span class="bouton" onclick="affiche_cache('prema',this)">Afficher</span>
41<div id="prema"><p class="petit">Si l'enfant est né prématuré (avant 37 semaines d'aménorrhée), indiquer de « combien » en durée (même syntaxe que pour les âges, voir plus bas). Sinon, laisser 0j.</p> 41<div id="prema"><p class="petit">Si l'enfant est né prématuré (avant 37 semaines d'aménorrhée), indiquer de « combien » en durée (même syntaxe que pour les âges, voir plus bas). Sinon, laisser 0j.</p>
42<label>Prématurité</label> <input type="text" name="prematurite" value="{{ valform.prematurite }}"> <input type="checkbox" name="agecorrige" {% if valform.agecorrige == "oui"%}checked{%endif%}> Afficher l'âge corrigé sur la courbe (plutôt que l'âge réel). 42<label>Prématurité</label> <input type="text" name="prematurite" value="{{ valform.prematurite }}"> <input type="checkbox" name="agecorrige"{% if valform.agecorrige == "oui"%} checked{%endif%}> Afficher l'âge corrigé sur la courbe (plutôt que l'âge réel).
43</div></li> 43</div></li>
44 44
45</ul> 45</ul>
@@ -48,7 +48,7 @@
48 48
49 49
50 50
51<h3>Données de l'enfant</h3> 51<h3>Saisir les données</h3>
52<p><span id="bouton_afficher_donneesplus" class="bouton" onclick="affiche_cache_classe('donneesplus')">Afficher</span> la saisie des tailles.</p> 52<p><span id="bouton_afficher_donneesplus" class="bouton" onclick="affiche_cache_classe('donneesplus')">Afficher</span> la saisie des tailles.</p>
53<p>Syntaxe pour l'âge&nbsp;: utiliser j, s, m, a comme des "unités" (jours, semaines, mois, années). Vous pouvez mixer les unités, par exemple "3a2m5j" pour 3 ans, 2 mois et 5 jours. Les espaces sont ignorées, et il faut saisir des nombres entiers.</p> 53<p>Syntaxe pour l'âge&nbsp;: utiliser j, s, m, a comme des "unités" (jours, semaines, mois, années). Vous pouvez mixer les unités, par exemple "3a2m5j" pour 3 ans, 2 mois et 5 jours. Les espaces sont ignorées, et il faut saisir des nombres entiers.</p>
54<p>Saisir le poids en kilogrammes (par exemple "2.62" ou "2,62" pour 2 kilogrammes et 620 grammes).</p> 54<p>Saisir le poids en kilogrammes (par exemple "2.62" ou "2,62" pour 2 kilogrammes et 620 grammes).</p>
@@ -93,10 +93,10 @@
93 {% endfor %} 93 {% endfor %}
94 </select></label></li> 94 </select></label></li>
95 <li><label>valeur maximum du graphique (facultatif, syntaxe similaire à l'âge) </label><input type="text" name="maxi" value="{{ valform.maxi }}"></li> 95 <li><label>valeur maximum du graphique (facultatif, syntaxe similaire à l'âge) </label><input type="text" name="maxi" value="{{ valform.maxi }}"></li>
96 <li>Prolonger les courbes (expérimental) : <input type="checkbox" name="prolongercourbes" {% if valform.prolongercourbes == "oui" %} checked{% endif%}></li>
97 96
98 <li><label>Même échelle sur tous les graphiques&nbsp;: </label><input type="checkbox" name="memechelle" {% if valform.memechelle == 'oui' %} checked{% endif %}></li> 97 <li><label>Même échelle sur tous les graphiques&nbsp;: </label><input type="checkbox" name="memechelle" {% if valform.memechelle == 'oui' %} checked{% endif %}></li>
99 <li><label>Grille améliorée (bêta)&nbsp;:</label><input type="checkbox" name="grilleamelio" {% if valform.grilleamelio == 'oui' %} checked{% endif %}></li> 98 <li><label>Grille améliorée&nbsp;:</label><input type="checkbox" name="grilleamelio" {% if valform.grilleamelio == 'oui' %} checked{% endif %}></li>
99
100 <li>Dimensions du graphique&nbsp;: <label>largeur&nbsp;: </label><input type="text" name="largeur" value="{{ valform.largeur }}"> 100 <li>Dimensions du graphique&nbsp;: <label>largeur&nbsp;: </label><input type="text" name="largeur" value="{{ valform.largeur }}">
101 <label>hauteur&nbsp;: </label><input type="text" name="hauteur" value="{{ valform.hauteur }}"></li> 101 <label>hauteur&nbsp;: </label><input type="text" name="hauteur" value="{{ valform.hauteur }}"></li>
102 <li><label>Légende&nbsp;: <input type="checkbox" name="legende" {% if valform.legende == 'oui' %} checked{% endif %}> </label> 102 <li><label>Légende&nbsp;: <input type="checkbox" name="legende" {% if valform.legende == 'oui' %} checked{% endif %}> </label>
@@ -112,6 +112,32 @@
112</ul> 112</ul>
113 113
114 114
115
116<!-- Section calculs/Extrapolation !-->
117
118<h3>Extrapolation</h3>
119<div class="bouton" onclick="affiche_cache('extra',this)">Afficher</div>
120
121<ul id="extra">
122 <li>Calculer le prolongement de la courbe à partir des <input type="text" name="nbextradata" size="4" value="1"> dernières données (mettre 0 pour "toutes").</li>
123 <li><input type="checkbox" name="prolongercourbes">Tracer l'extrapolation sur le graphique.</li>
124 <li>Calculer <select name="calculextradata_type">
125 <option value="">Choisir la donnée</option>
126 {% for val in CONFIG.liste_typedonnees %}
127 <option value="{{val}}">{{val}}</option>
128 {% endfor %}
129 </select> à l'âge <input type="text" name="calculextradata_age" value="6m"></li>
130 <li>Calculer l'âge auquel l'enfant aura <input type="text" name="calculextratemps_val">
131 <select name="calculextratemps_type">
132 <option value="">Choisir la donnée</option>
133 {% for val in CONFIG.liste_typedonnees %}
134 <option value="{{val}}">{{ CONFIG.unites_typedonnees[val]}} ({{val}})</option>
135 {% endfor %}
136 </select></li>
137
138</ul>
139
140
115</form> 141</form>
116<!-- section retour --> 142<!-- section retour -->
117<hr> 143<hr>
@@ -153,6 +179,13 @@
153 179
154</div> 180</div>
155 181
182<div id="section_extradonnees">
183 <h2>Calculs sur les courbes</h2>
184 <ul id="extradata">
185
186 </ul>
187</div>
188
156 189
157<div id="sectionexport"> 190<div id="sectionexport">
158 <h2>Export des données</h2> 191 <h2>Export des données</h2>
diff --git a/trace_courbe.py b/trace_courbe.py
index c3e1691..e725607 100644
--- a/trace_courbe.py
+++ b/trace_courbe.py
@@ -3,21 +3,24 @@
3from configuration import CONFIG 3from configuration import CONFIG
4import gestionOMS as oms 4import gestionOMS as oms
5import gestion_unites as u 5import gestion_unites as u
6from gestion_donnees import calcule_max_graphique, convertit_jours_vers_python 6from gestion_donnees import calcule_max_graphique, convertit_jours_vers_python, convertit_age_vers_texte
7from gestion_erreurs import debug, erreur, warning 7from gestion_erreurs import debug, erreur, warning
8from numpy import arange 8from numpy import arange
9from calculs_extrapole import calcule_donnee_extrapolee, calcule_age_extrapole
9 10
10import matplotlib.pyplot as plt 11import matplotlib.pyplot as plt
11 12
12# Essentiellement, la fonction qui trace la courbe 13# Essentiellement, la fonction qui trace la courbe, mais on y trouve également les fonctions d'extrapolation.
14# Ainsi que les calculs additionnels.
13 15
14 16
15def cree_figure(conf,l_jours,l_poids,typedonnee,liste_err): 17def cree_figure(conf,l_jours,l_poids,typedonnee,liste_extracalculs, liste_err):
16 """ conf est le dictionnaire de config. l_jours et l_poids les listes des temps (en jours) et de données 18 """ conf est le dictionnaire de config. l_jours et l_poids les listes des temps (en jours) et de données
17 (donc pas forcément du poids) 19 (donc pas forcément du poids)
18 typedonnee est le type de données (voir CONFIG["liste_typedonnees"] 20 typedonnee est le type de données (voir CONFIG["liste_typedonnees"]
19 liste_err la liste des erreurs à compléter (voir gestion_erreurs)) 21 liste_err la liste des erreurs à compléter (voir gestion_erreurs))
20 Renvoie la figure tracée""" 22 Renvoie la figure tracée, et les calculs additionnels sont mis sous forme de chaîne dans la liste
23 liste_extracalculs"""
21 debug("debut de cree_figure. Config : "+str(conf),liste_err) 24 debug("debut de cree_figure. Config : "+str(conf),liste_err)
22 try: 25 try:
23 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) 26 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)
@@ -156,19 +159,64 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_err):
156 debug("Tracé de la courbe enfant, avec les jours "+str(l_jours_conv),liste_err) 159 debug("Tracé de la courbe enfant, avec les jours "+str(l_jours_conv),liste_err)
157 160
158 #### extrapolatios éventuelles 161 #### extrapolatios éventuelles
159 #print("prolongercourbes" in conf) 162 # a-t-on demndé des calculs ?
160 if conf["prolongercourbes"] == "oui": 163 jextrapole = conf["non_sauve"]["prolongercourbes"] == "oui"
161 #print("coucou") 164 # Est-ce qu'on a demandé un calcul sur cette donnée ?
162 # les dates, on prend tous les jours tant qu'à faire 165 print()
163 date_fin = int(l_jours[-1]) 166 for calextra in CONFIG["extradata"]:
164 dates_extrapole = list(range(date_fin, jour_maxi)) 167 jextrapole = jextrapole or conf["non_sauve"][calextra+"_type"] == typedonnee
165 donnees_extrapole = prolongecourbe(t, date_fin, l_poids[-1], dates_extrapole, conf["typecourbe"], liste_err) 168
166 #print("données extrapolées !") 169 #print(jextrapole)
167 dates_extrapole = u.convertit_tableau(dates_extrapole,unite,liste_err) 170 if jextrapole:
168 171 try:
169 # tracé des données extrapolées 172 debug("Il faut extrapoler les courbes !", liste_err)
170 plt.plot(dates_extrapole, donnees_extrapole,color=conf["couleurs"]["cadretxt"], linestyle=(0, (5,7)), marker=None) 173 # Prendre l'ensemble des dates "source"
171 debug("Tracé de la courbe extrapolée ok", liste_err) 174 # print(conf["non_sauve"]["nbdataextra"])
175 if conf["non_sauve"]["nbextradata"] == 0:
176 sources_extrap = l_jours
177 sources_extrap_data = l_poids
178 else:
179 sources_extrap = l_jours[-conf["non_sauve"]["nbextradata"]:] # les derniers jours
180 sources_extrap_data = l_poids[-conf["non_sauve"]["nbextradata"]:]
181
182 debug("On extrapole sur les jours : "+str(sources_extrap), liste_err)
183
184 dates_extrapole, donnees_extrapole = prolongecourbe(t, sources_extrap, sources_extrap_data, conf["typecourbe"], liste_err)
185 debug("données extrapolées !", liste_err)
186 #debug(str(dates_extrapole[0:10])+str(donnees_extrapole[0:10]), liste_err)
187
188 # QUe veut-on maintenant sur ces données extrapolées ?
189 # Afficher la courbe
190 if conf["non_sauve"]["prolongercourbes"] == "oui":
191 # On va prendre les extrapolations de la dernière donnée jusqu'à l fin du graphe
192 debut_extr = int(l_jours[-conf["non_sauve"]["nbextradata"]])
193 i_debut_extr = dates_extrapole.index(debut_extr)
194 i_fin_extr = dates_extrapole.index(jour_maxi)
195 # Voilà ce qu'on veut tracer
196 dates_extrapole_trace = dates_extrapole[i_debut_extr:i_fin_extr+1]
197 donnees_extrapole_trace = donnees_extrapole[i_debut_extr:i_fin_extr+1]
198 dates_extrapole_trace = u.convertit_tableau(dates_extrapole_trace,unite,liste_err)
199
200 # tracé des données extrapolées
201 plt.plot(dates_extrapole_trace, donnees_extrapole_trace,color=conf["couleurs"]["cadretxt"], linestyle=(0, (5,7)), marker=None)
202 debug("Tracé de la courbe extrapolée ok", liste_err)
203
204 # Calculer une donnée à l'âge x
205 if conf["non_sauve"]["calculextradata_type"] == typedonnee:
206 r = calcule_donnee_extrapolee(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextradata_age"], typedonnee, liste_err)
207 if r!="":
208 liste_extracalculs.append(r)
209 print(liste_extracalculs)
210
211 # Calculer un âge où on atteint cette donnée
212 if conf["non_sauve"]["calculextratemps_type"] == typedonnee:
213 r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], typedonnee, liste_err)
214 if r!="":
215 liste_extracalculs.append(r)
216 print(liste_extracalculs)
217
218 except:
219 warning("Des problèmes pour extrapoler...", liste_err)
172 220
173 else: 221 else:
174 debug("On ne trace pas de courbe enfant", liste_err) 222 debug("On ne trace pas de courbe enfant", liste_err)
@@ -239,14 +287,11 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_err):
239 287
240 plt.xlabel("Âge en "+unite,color=conf["couleurs"]["cadretxt"]) 288 plt.xlabel("Âge en "+unite,color=conf["couleurs"]["cadretxt"])
241 plt.ylabel(typedonnee.capitalize()+" en "+CONFIG["unites_typedonnees"][typedonnee],color=conf["couleurs"]["cadretxt"]) 289 plt.ylabel(typedonnee.capitalize()+" en "+CONFIG["unites_typedonnees"][typedonnee],color=conf["couleurs"]["cadretxt"])
242 #print("bla")
243 plt.title(titre,color=conf["couleurs"]["cadretxt"]) 290 plt.title(titre,color=conf["couleurs"]["cadretxt"])
244 #print("ble")
245 if l_jours_conv == []: 291 if l_jours_conv == []:
246 plt.axis([0,age_maxi, poids_min, poids_max]) 292 plt.axis([0,age_maxi, poids_min, poids_max])
247 else: 293 else:
248 plt.axis([min(0,l_jours_conv[0]),age_maxi,poids_min,poids_max]) 294 plt.axis([min(0,l_jours_conv[0]),age_maxi,poids_min,poids_max])
249 #print("bli")
250 295
251 296
252 if conf['legende']=="oui": 297 if conf['legende']=="oui":
@@ -264,43 +309,66 @@ def cree_figure(conf,l_jours,l_poids,typedonnee,liste_err):
264 309
265######################################## Pour extrapoler la courbe 310######################################## Pour extrapoler la courbe
266 311
267def prolongecourbe(tableauOMS, date, donnee, nouvdates, typecourbe, liste_err): 312def prolongecourbe(tableauOMS, dates, donnees, typecourbe, liste_err):
268 """ tableauOMS est le ableau des données OMS. date et donnee sont la date (jours) 313 """ tableauOMS est le ableau des données OMS. dates et donnees sont les dates (jours)
269 et la dernière donnée d'où on extrapole. On veut les extrapolations à nouvdate 314 et les données d'où on extrapole. On calcule toutes les dates comme des sauvages.
315 On renvoie la liste des jours totale et la liste des data_totales
270 (tableaux de jours) 316 (tableaux de jours)
271 typecourbe est P ou Z. Pour P il faut commencer à regarder à l'indice 4, pour Z 317 typecourbe est P ou Z. Pour P il faut commencer à regarder à l'indice 4, pour Z
272 à l'indice 1 318 à l'indice 1
273 On renvoie [] si pas pu extrapoler. """ 319 On renvoie [],[] si pas pu extrapoler. """
320 # les lignes OMS correspondant aux dates données
321 lignesoms = [tableauOMS[int(date)] for date in dates]
322 debug("prolongecourbe : Lignes OMS :"+str(lignesoms)+" valeur de données : "+str(donnees), liste_err)
274 323
275 # la ligne OMS
276 ligneoms = tableauOMS[date]
277 debug("prolongecourbe : Ligne OMS :"+str(ligneoms)+" valeur de donnée : "+str(donnee), liste_err)
278 324
279 325
280 # On cherche dans quel intervalle on se situe 326 # Principe : on cherche dans quel intervalle de "colonnes" on se situe.
327 # On va donc regarder pour chaque donnée entre quels i on se situe,et après
328 # prendre le plus grand intervalle.
329 # Numéros de colonnes d'où on part. Pour la fin c'est forcément longueur-1
281 if typecourbe == "P": 330 if typecourbe == "P":
282 idep=4 331 idep=4
283 else: 332 else:
284 idep = 1 333 idep = 1
285 i = idep 334
286 while i<len(ligneoms) and ligneoms[i]<donnee: 335 liste_indices = []
287 i+=1 336 for k in range(len(dates)):
288 debug("prolongecourbe : on a trouvé la valeur de i : "+str(i),liste_err) 337 i= idep
289 if i>=len(ligneoms): 338 ligne = lignesoms[k]
290 warning("prolongation de courbe : pas réussi... donnée trop haute !", liste_err) 339 while i<len(ligne) and ligne[i]<donnees[k]:
291 return [] 340 i+=1
292 if i==idep: 341 debug("prolongecourbe : on a trouvé la valeur de i : "+str(i),liste_err)
293 warning("prolongation de courbe : pas réussi... donnée trop basse !", liste_err) 342 if i>=len(ligne):
294 return [] 343 warning("prolongation de courbe : pas réussi... donnée trop haute !", liste_err)
344 return [],[]
345 if i==idep:
346 warning("prolongation de courbe : pas réussi... donnée trop basse !", liste_err)
347 return [],[]
348 liste_indices.append(i)
349 imin=min(liste_indices) -1
350 imax=max(liste_indices)
351 debug("Les données se situent dans les indices : "+str(imin)+", "+str(imax),liste_err)
352 # Maintenant on doit trouver les coeffs : on se situe en coeff * l[imin]+ (1-coeff)*ligne[imax]
353 # Et faire la moyenne de ces coeffs
354 total = 0
355 for k in range(len(dates)):
356 ligne = lignesoms[k]
357 donnee = donnees[k]
358 total += (donnee - ligne[imax])/(ligne[imin] - ligne[imax])
359 #print(k)
360 coeff_moyen = total/len(dates)
361
362 debug("Coeff moyen calculé : "+str(coeff_moyen), liste_err)
295 363
296 # Le coeff : donnee = coeff * l[i-1]+ (1-coeff)*ligne[i] 364 # On utilisera la même chose pour les nouvelle donnee
297 # On utilisera la même chose pour la nouvelle donnee
298 coeff = (donnee - ligneoms[i])/(ligneoms[i-1] - ligneoms[i])
299 365
300 # extrapolations 366 # extrapolations
367 nouvdates =oms.extraire_colonne(tableauOMS,0) # On sort tout.
368 #print(nouvdates)
301 nouvdonnees = [] 369 nouvdonnees = []
302 for j in nouvdates: 370 for j in nouvdates:
303 ligne2 = tableauOMS[j] 371 ligne2 = tableauOMS[int(j)]
304 nouvdonnees.append(coeff*ligne2[i-1]+ (1-coeff)*ligne2[i]) 372 nouvdonnees.append(coeff_moyen*ligne2[imin]+ (1-coeff_moyen)*ligne2[imax])
305 373
306 return nouvdonnees \ No newline at end of file 374 return nouvdates,nouvdonnees \ No newline at end of file