from configuration import CONFIG
from gestion_donnees import convertit_age_vers_texte
import gestion_unites as u
+from math import ceil
-#### Les fonctions qui permettent de faire les calculs additionnels une fois qu'on a l'extrapolation
+#### Les fonctions qui permettent de faire les calculs additionnels une fois qu'on a l'extrapolation (ou pas)
+
+def interpole_lineaire(dates, donnees, t, liste_err):
+ """ simple interpolation linéaire.
+ dates et donnees sont les dates et données de l'enfant.
+ t est le temps (jours) auquel on veut l'interpolation. On renvoie la donnée interpolée.
+ On interpole linéairement entre les deux données. Si ça
+ n'est pas possible parce que t n'est pas dans les bornes, on renvoie -1
+ """
+
+ if t<dates[0] or t>dates[-1]:
+ return -1 # en dehors des bornes
+
+ i=0 # on cherche l'intervalle : entre dates[i] et dates[i+1] on a la donnée t
+ while i<len(dates)-1 and dates[i+1]<t:
+ i+=1
+
+ m = (donnees[i+1] - donnees[i])/(dates[i+1] - dates[i]) # pente de la courbe
+ valeur = m * (t - dates[i]) + donnees[i]
+ return valeur
+
+
+def interpole_lineaire_ordonnee(dates, donnees, val, liste_err):
+ """ interpolation linéaire des données.
+ dates et donnees sont les dates et données de l'enfant.
+ val est la valeur pour laquelle on veut trouver le temps.
+ On interpole linéairement entre les deux données. Si ça
+ n'est pas possible parce que t n'est pas dans les bornes, on renvoie -1
+
+ Comportement potentiellement foireux si jamais les données ne sont pas
+ croissantes (poids qui chute, etc)..."""
+
+ if val>max(donnees) or val<min(donnees):
+ return -1 # en dehors des maxi et mini
+
+ i = 0 # On cherche dans quel intervalles de données on se situe (donnnes[i]
+ # et donnees [i+1])
+ while i<len(donnees)-1 and donnees[i+1]<val:
+ i+=1
+
+ m = (dates[i+1] - dates[i])/(donnees[i+1] - donnees[i])
+ temps = m * (val - donnees[i]) + dates[i]
+
+ return ceil(temps)
+
+
+######################################
+
+
+
+
+
+def calcule_donnee_extrapolee(dates_extrapole, donnees_extrapole, age_voulu, liste_err):
+ """ prend en argument les données extrapolées, l'âge voulu en jours.
+ Renvoie la donnée, ou -1 si ça n'a pas marché"""
+ age_voulu = int(age_voulu) # pour avoir les choses bien
+ debug("On veut la donnée à l'âge "+str(age_voulu), liste_err)
+ try:
+ i_date_voulue = dates_extrapole.index(age_voulu)
+ donnee_voulue = donnees_extrapole[i_date_voulue]
+
+ return donnee_voulue
+ #return formate_resultat_donnee(age_voulu, donnee_voulue, typedonnee, "", liste_err)
+ except:
+ warning("Impossible de calculer la donnée à l'âge "+age_voulu, liste_err)
+ return -1
+
+
+
+def calcule_age_extrapole(dates_extrapole, donnees_extrapole, donnee_voulue, liste_err):
+ """ prend en argument les données extrapolées, la donnée voulue (dans l'unité adaptée)
+ Renvoie la donnée, ou -1 si ça n'a pas marché"""
+
+ debug("On veut savoir à quel âge on a "+str(donnee_voulue), liste_err)
+ try:
+ i=0
+ while i<len(donnees_extrapole) and donnees_extrapole[i]<donnee_voulue:
+ i+=1
+
+ return dates_extrapole[i]
+ #return formate_resultat_age(dates_extrapole[i], donnee_voulue, typedonnee, "", liste_err)
+ except:
+ warning("Impossible de calculer l'âge pour la donnée "+str(donnee_voulue), liste_err)
+ return -1
+
+######################################
+### Formatage du résultat "joli"
def met_s(chaine):
""" renvoie un s si pluriel, rien sinon"""
nombre = ""
for char in age:
if char=="a":
- retour+=nombre+" année"+met_s(nombre)+", "
+ retour+=nombre+" an"+met_s(nombre)+", "
nombre=""
elif char=="m":
retour+=nombre+" mois, "
nombre+=char
#print(retour)
return retour[:-2]
-
+def formate_resultat_donnee(age, donnee, typedonnee, extra, liste_err):
+ """ Formate le tout en une zolie phrase
+ age et donnee sont les données,
+ typedonnee est le type de donnée (poids, etc)
+ extra est un truc additionnel à mettre entre parenthèses"""
-def calcule_donnee_extrapolee(dates_extrapole, donnees_extrapole, age_voulu, typedonnee, liste_err):
- """ prend en argument les données extrapolées, l'âge voulu en jours,
- et le type de données qu'on veut afficher, et renvoie une jolie phrase
- à afficher"""
- age_voulu = int(age_voulu) # pour avoir les choses bien
- debug("On veut la donnée à l'âge "+str(age_voulu), liste_err)
- try:
- i_date_voulue = dates_extrapole.index(age_voulu)
- donnee_voulue = donnees_extrapole[i_date_voulue]
- donnee_arrondie = u.arrondit_donnee(donnee_voulue, typedonnee)
- chaine = "À "+joliechaine_age(convertit_age_vers_texte(age_voulu))
-
- if typedonnee == "poids":
- return chaine+", l'enfant pèsera "+str(donnee_arrondie)+" kg."
- elif typedonnee == "taille":
- return chaine+", l'enfant mesurera "+str(donnee_arrondie)+" cm."
- else: # phrase générique
- return chaine+", la donnée sera : "+str(donnee_arrondie)+" "+CONFIG["unites_typedonnees"][typedonnee]+"."
- except:
- warning("Impossible de calculer la donnée à l'âge "+age_voulu, liste_err)
- return ""
-
-def calcule_age_extrapole(dates_extrapole, donnees_extrapole, donnee_voulue, typedonnee, liste_err):
- """ prend en argument les données extrapolées, la donnée voulue (dans l'unité adaptée)
- et son type, et renvoie la jolie phrase à afficher"""
+ donnee_arrondie = u.arrondit_donnee(donnee, typedonnee)
+ chaine = "À "+joliechaine_age(convertit_age_vers_texte(age))
+
+ if typedonnee == "poids":
+ chaine+= ", l'enfant pèsera "+str(donnee_arrondie)+" kg"
+ elif typedonnee == "taille":
+ chaine+= ", l'enfant mesurera "+str(donnee_arrondie)+" cm"
+ else: # phrase générique
+ chaine+= ", la donnée sera : "+str(donnee_arrondie)+" "+CONFIG["unites_typedonnees"][typedonnee]
+
+ if extra!="":
+ ajout=" ("+extra+")"
+ else:
+ ajout=""
+
+ chaine+=ajout+"."
+ return chaine
+
+def formate_resultat_age(age, donnee, typedonnee, extra, liste_err):
+ """ formate les données en une zolie phrase
+ age et donnee sont les données
+ typedonnee est le type de donnée (poids, etc)
+ extra est un truc additionnel à mettre entre parenthèses"""
+ age_joli = joliechaine_age(convertit_age_vers_texte(age))
+ if typedonnee=="poids":
+ chaine= "L'enfant atteindra un poids de "+str(donnee)+" kg à l'âge de "+age_joli
+ elif typedonnee=="taille":
+ chaine= "L'enfant atteindra la taille "+str(donnee)+ "cm à l'âge de "+age_joli
+ else:# phrase générique
+ chaine= "L'enfant atteindra la donnée "+typedonnee+" "+str(donnee)+" à l'âge de "+age_joli
- debug("On veut savoir à quel âge on a "+str(donnee_voulue), liste_err)
- try:
- i=0
- while i<len(donnees_extrapole) and donnees_extrapole[i]<donnee_voulue:
- i+=1
-
- age_joli = joliechaine_age(convertit_age_vers_texte(dates_extrapole[i]))
- if typedonnee=="poids":
- return "L'enfant atteindra un poids de "+str(donnee_voulue)+" kg à l'âge de "+age_joli+"."
- elif typedonnee=="taille":
- return "L'enfant atteindra la taille "+str(donnee_voulue)+ "cm à l'âge de "+age_joli+"."
- else:# phrase générique
- return "L'enfant atteindra la donnée "+typedonnee+" "+str(donnee_voulue)+" à l'âge de "+age_joli+"."
- except:
- warning("Impossible de calculer l'âge pour la donnée "+str(donnee_voulue), liste_err)
- return ""
+ if extra!="":
+ ajout=" ("+extra+")"
+ else:
+ ajout=""
+
+ chaine+=ajout+"."
+ return chaine
+
+def formate_extrapole(nb_extra):
+ """ Renvoie une chaîne qui dit sur cb on a extrapolé"""
+ message="extrapolation sur "
+ if nb_extra== 0:
+ message+="l'ensemble des données"
+ elif nb_extra==1:
+ message+="la donnée la plus récente"
+ else:
+ message+="les "+str(nb_extra)+" dernières données"
+ return message
+
+def formate_interpole():
+ return "interpolation sur les données existantes"
\ No newline at end of file
import gestion_unites as u
from gestion_donnees import calcule_max_graphique, convertit_jours_vers_python, convertit_age_vers_texte
from gestion_erreurs import debug, erreur, warning
+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
+
from numpy import arange
-from calculs_extrapole import calcule_donnee_extrapolee, calcule_age_extrapole
+
import matplotlib.pyplot as plt
jextrapole = jextrapole or conf["non_sauve"][calextra+"_type"] == typedonnee
#print(jextrapole)
+ ############################## Là où on extrapole ################################
if jextrapole:
try:
debug("Il faut extrapoler les courbes !", liste_err)
debug("On extrapole sur les jours : "+str(sources_extrap), liste_err)
+ # On récupère toutes les données extrapolées
dates_extrapole, donnees_extrapole = prolongecourbe(t, sources_extrap, sources_extrap_data, conf["typecourbe"], liste_err)
debug("données extrapolées !", liste_err)
#debug(str(dates_extrapole[0:10])+str(donnees_extrapole[0:10]), liste_err)
plt.plot(dates_extrapole_trace, donnees_extrapole_trace,color=conf["couleurs"]["cadretxt"], linestyle=(0, (5,7)), marker=None)
debug("Tracé de la courbe extrapolée ok", liste_err)
- # Calculer une donnée à l'âge x
+ ### Calculer une donnée à l'âge x
if conf["non_sauve"]["calculextradata_type"] == typedonnee:
- r = calcule_donnee_extrapolee(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextradata_age"], typedonnee, liste_err)
- if r!="":
- liste_extracalculs.append(r)
+ # On essaie l'interpolation
+ r = interpole_lineaire(l_jours,l_poids,conf["non_sauve"]["calculextradata_age"], liste_err)
+ if r==-1:
+ # ça sera donc une extrapolation
+ r = calcule_donnee_extrapolee(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextradata_age"], liste_err)
+ message=formate_extrapole(conf["non_sauve"]["nbextradata"])
+# if == 0:
+# message+="l'ensemble des données"
+# else:
+# message+="les "+str(conf["non_sauve"]["nbextradata"])+" dernière"+met_s(conf["non_sauve"]["nbextradata"])+" données"
+ else:
+ message=formate_interpole()
+
+ texte = formate_resultat_donnee(conf["non_sauve"]["calculextradata_age"], r, typedonnee, message, liste_err)
+ debug("calcul de la donnée extrapolée : "+texte, liste_err)
+ if texte!="":
+ liste_extracalculs.append(texte)
print(liste_extracalculs)
+ # Ajouter le trait ?
+ if conf["non_sauve"]["calculextradata_trace"] == "oui":
+ dessine_guides(conf["non_sauve"]["calculextradata_age"], r, conf["couleurs"]["cadretxt"], unite, ax, liste_err)
- # Calculer un âge où on atteint cette donnée
+ ### Calculer un âge où on atteint cette donnée
if conf["non_sauve"]["calculextratemps_type"] == typedonnee:
- r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], typedonnee, liste_err)
- if r!="":
- liste_extracalculs.append(r)
+ # interpolation
+ r = interpole_lineaire_ordonnee(l_jours,l_poids,conf["non_sauve"]["calculextratemps_val"], liste_err)
+ if r==-1:
+ # ça sera donc une extrapolation
+ r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], liste_err)
+ message=formate_extrapole(conf["non_sauve"]["nbextradata"])
+ else:
+ message=formate_interpole()
+
+ texte = formate_resultat_age(r, conf["non_sauve"]["calculextratemps_val"], typedonnee, message, liste_err)
+
+ #r = calcule_age_extrapole(dates_extrapole, donnees_extrapole, conf["non_sauve"]["calculextratemps_val"], typedonnee, liste_err)
+ if texte!="":
+ liste_extracalculs.append(texte)
print(liste_extracalculs)
+ # Ajouter le trait ?
+ if conf["non_sauve"]["calculextratemps_trace"]:
+ dessine_guides(r, conf["non_sauve"]["calculextratemps_val"], conf["couleurs"]["cadretxt"], unite, ax, liste_err)
except:
warning("Des problèmes pour extrapoler...", liste_err)
ligne2 = tableauOMS[int(j)]
nouvdonnees.append(coeff_moyen*ligne2[imin]+ (1-coeff_moyen)*ligne2[imax])
- return nouvdates,nouvdonnees
\ No newline at end of file
+ return nouvdates,nouvdonnees
+
+
+def dessine_guides(t, data, couleur, unite, ax, liste_err):
+ """ dessine deux lignes, horizontales et verticales qui vont "vers" la courbe
+ jusqu'aux points (t, data). En pointillés et avec un point dessus."""
+ debug("Début de dessine_guides"+str(t)+", "+str(data), liste_err)
+ t_conv = u.convertitunite(t,unite,liste_err)
+ ax.vlines(t_conv, 0, data, colors=couleur, linestyles="dashed")
+ ax.hlines(data, 0, t_conv, color=couleur, linestyles="dashed")
+ ax.plot([t_conv], [data], color=couleur, marker="*", ms=13)