forked from ScoDoc/ScoDoc
Ménage + Ajout du détail des calculs (sem, trajectoires, interclassements taggués) au zip final dans un répertoire details (pouvant servir au debug)
This commit is contained in:
parent
cb5df2fffd
commit
9c6d988fc3
@ -372,3 +372,5 @@ def get_cosemestres_diplomants(
|
||||
cosemestres[fid] = cosem
|
||||
|
||||
return cosemestres
|
||||
|
||||
|
||||
|
@ -10,14 +10,6 @@ import numpy as np
|
||||
|
||||
|
||||
class AggregatInterclasseTag(TableTag):
|
||||
"""Interclasse l'ensemble des étudiants diplômés à une année
|
||||
donnée (celle du jury), pour un aggrégat donné (par ex: 'S2', '3S')
|
||||
en reportant :
|
||||
|
||||
* les moyennes obtenues sur la trajectoire qu'il ont suivi pour atteindre le numéro de semestre de fin de l'aggrégat (indépendamment de son
|
||||
formsemestres)
|
||||
* calculant le classement sur les étudiants diplômes
|
||||
"""
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def __init__(
|
||||
@ -27,12 +19,26 @@ class AggregatInterclasseTag(TableTag):
|
||||
trajectoires_jury_pe: TrajectoiresJuryPE,
|
||||
trajectoires_taggues: dict[tuple, TrajectoireTag],
|
||||
):
|
||||
# Table nommée au nom de l'aggrégat (par ex: 3S)
|
||||
TableTag.__init__(self, nom_aggregat)
|
||||
"""
|
||||
Interclasse l'ensemble des étudiants diplômés à une année
|
||||
donnée (celle du jury), pour un aggrégat donné (par ex: 'S2', '3S')
|
||||
en reportant :
|
||||
|
||||
* les moyennes obtenues sur la trajectoire qu'il ont suivi pour atteindre le numéro de semestre de fin de l'aggrégat (indépendamment de son
|
||||
formsemestres)
|
||||
* calculant le classement sur les étudiants diplômes
|
||||
"""
|
||||
TableTag.__init__(self)
|
||||
|
||||
# Le nom
|
||||
self.aggregat = nom_aggregat
|
||||
self.nom = self.get_repr()
|
||||
|
||||
"""Les étudiants diplômés et leurs trajectoires (cf. trajectoires.suivis)""" # TODO
|
||||
self.diplomes_ids = etudiants.etudiants_diplomes
|
||||
self.etudiants_diplomes = {etudid for etudid in self.diplomes_ids}
|
||||
# pour les exports sous forme de dataFrame
|
||||
self.etudiants = {etudid: etudiants.identites[etudid].etat_civil for etudid in self.diplomes_ids}
|
||||
|
||||
# Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
|
||||
self.trajectoires: dict[int, Trajectoire] = {}
|
||||
@ -73,9 +79,13 @@ class AggregatInterclasseTag(TableTag):
|
||||
"nb_inscrits": len(moy_gen_tag),
|
||||
}
|
||||
|
||||
# Est significatif ? (aka a-t-il des tags et des notes)
|
||||
self.significatif = len(self.tags_sorted) > 0
|
||||
|
||||
|
||||
def get_repr(self) -> str:
|
||||
"""Une représentation textuelle"""
|
||||
return f"Aggrégat {self.nom}"
|
||||
return f"Aggrégat {self.aggregat}"
|
||||
|
||||
def do_taglist(self):
|
||||
"""Synthétise les tags à partir des trajectoires_tagguées
|
||||
|
@ -121,7 +121,7 @@ class JuryPE(object):
|
||||
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||||
for formsemestretag in self.semestres_taggues.values():
|
||||
onglet = formsemestretag.nom
|
||||
df = formsemestretag.df_semtag()
|
||||
df = formsemestretag.df_moyennes_et_classements()
|
||||
# écriture dans l'onglet
|
||||
df.to_excel(writer, onglet, index=True, header=True)
|
||||
output.seek(0)
|
||||
@ -149,17 +149,22 @@ class JuryPE(object):
|
||||
self.trajectoires, self.etudiants, self.semestres_taggues
|
||||
)
|
||||
|
||||
if pe_affichage.PE_DEBUG:
|
||||
# Intègre le bilan des trajectoires tagguées au zip final
|
||||
# Intègre le bilan des trajectoires tagguées au zip final
|
||||
output = io.BytesIO()
|
||||
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||||
for trajectoire_tagguee in self.trajectoires_tagguees.values():
|
||||
filename = trajectoire_tagguee.get_repr().replace(" ", "_") + ".csv"
|
||||
# pe_affichage.pe_print(f" - Export csv de {filename} ")
|
||||
self.add_file_to_zip(
|
||||
zipfile,
|
||||
filename,
|
||||
trajectoire_tagguee.str_tagtable(),
|
||||
path="details_semestres",
|
||||
)
|
||||
onglet = trajectoire_tagguee.get_repr()
|
||||
df = trajectoire_tagguee.df_moyennes_et_classements()
|
||||
# écriture dans l'onglet
|
||||
df.to_excel(writer, onglet, index=True, header=True)
|
||||
output.seek(0)
|
||||
|
||||
self.add_file_to_zip(
|
||||
zipfile,
|
||||
f"trajectoires_taggues_{self.diplome}.xlsx",
|
||||
output.read(),
|
||||
path="details",
|
||||
)
|
||||
|
||||
# Génère les interclassements (par promo et) par (nom d') aggrégat
|
||||
pe_affichage.pe_print("*** Génère les interclassements par aggrégat")
|
||||
@ -167,17 +172,23 @@ class JuryPE(object):
|
||||
self.etudiants, self.trajectoires, self.trajectoires_tagguees
|
||||
)
|
||||
|
||||
if pe_affichage.PE_DEBUG:
|
||||
# Intègre le bilan des aggrégats (par promo) au zip final
|
||||
# Intègre le bilan des aggrégats (interclassé par promo) au zip final
|
||||
output = io.BytesIO()
|
||||
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||||
for interclass_tag in self.interclassements_taggues.values():
|
||||
filename = interclass_tag.get_repr().replace(" ", "_") + ".csv"
|
||||
# pe_affichage.pe_print(f" - Export csv de {filename} ")
|
||||
self.add_file_to_zip(
|
||||
zipfile,
|
||||
filename,
|
||||
interclass_tag.str_tagtable(),
|
||||
path="details_semestres",
|
||||
)
|
||||
if interclass_tag.significatif: # Avec des notes
|
||||
onglet = interclass_tag.get_repr()
|
||||
df = interclass_tag.df_moyennes_et_classements()
|
||||
# écriture dans l'onglet
|
||||
df.to_excel(writer, onglet, index=True, header=True)
|
||||
output.seek(0)
|
||||
|
||||
self.add_file_to_zip(
|
||||
zipfile,
|
||||
f"interclassements_taggues_{self.diplome}.xlsx",
|
||||
output.read(),
|
||||
path="details",
|
||||
)
|
||||
|
||||
# Synthèse des éléments du jury PE
|
||||
self.synthese = self.synthetise_juryPE()
|
||||
@ -437,7 +448,7 @@ def compute_trajectoires_tag(
|
||||
nom = trajectoire.get_repr()
|
||||
pe_affichage.pe_print(f" --> Aggrégat {nom}")
|
||||
# Trajectoire_tagguee associée
|
||||
trajectoire_tagguee = TrajectoireTag(nom, trajectoire, semestres_taggues)
|
||||
trajectoire_tagguee = TrajectoireTag(trajectoire, semestres_taggues)
|
||||
# Mémorise le résultat
|
||||
trajectoires_tagguees[trajectoire_id] = trajectoire_tagguee
|
||||
|
||||
|
@ -61,7 +61,7 @@ class SemestreTag(TableTag):
|
||||
nom: Nom à donner au SemestreTag
|
||||
formsemestre_id: Identifiant du ``FormSemestre`` sur lequel il se base
|
||||
"""
|
||||
# TableTag.__init__(self, nom=nom)
|
||||
TableTag.__init__(self)
|
||||
|
||||
# Le semestre
|
||||
self.formsemestre_id = formsemestre_id
|
||||
@ -126,7 +126,7 @@ class SemestreTag(TableTag):
|
||||
# Synthétise l'ensemble des moyennes dans un dataframe
|
||||
self.tags_sorted = sorted(self.moyennes_tags) # les tags par ordre alphabétique
|
||||
self.notes = (
|
||||
self.df_tagtable()
|
||||
self.df_notes()
|
||||
) # Le dataframe synthétique des notes (=moyennes par tag)
|
||||
|
||||
pe_affichage.pe_print(f" => Traitement des tags {', '.join(self.tags_sorted)}")
|
||||
@ -282,28 +282,7 @@ class SemestreTag(TableTag):
|
||||
# Sinon - pas de notes à prendre en compte
|
||||
return (note, coeff_norm)
|
||||
|
||||
def df_semtag(self):
|
||||
"""Renvoie un dataframe listant toutes les moyennes,
|
||||
les rangs des étudiants pour tous les tags dans le semestre taggué"""
|
||||
|
||||
etudiants = self.etudiants
|
||||
df = pd.DataFrame.from_dict(etudiants, orient="index", columns=["nom"])
|
||||
|
||||
for tag in self.get_all_tags():
|
||||
df = df.join(self.moyennes_tags[tag]["notes"].rename(f"Moy {tag}"))
|
||||
df = df.join(self.moyennes_tags[tag]["classements"].rename(f"Class {tag}"))
|
||||
|
||||
return df
|
||||
|
||||
# ************************************************************************
|
||||
# Fonctions diverses
|
||||
# ************************************************************************
|
||||
|
||||
|
||||
# *********************************************
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def get_moduleimpl(modimpl_id) -> dict:
|
||||
"""Renvoie l'objet modimpl dont l'id est modimpl_id"""
|
||||
modimpl = db.session.get(ModuleImpl, modimpl_id)
|
||||
@ -317,7 +296,6 @@ def get_moduleimpl(modimpl_id) -> dict:
|
||||
return None
|
||||
|
||||
|
||||
# **********************************************
|
||||
def get_moy_ue_from_nt(nt, etudid, modimpl_id) -> float:
|
||||
"""Renvoie la moyenne de l'UE d'un etudid dans laquelle se trouve
|
||||
le module de modimpl_id
|
||||
|
@ -48,38 +48,13 @@ TAGS_RESERVES = ["but"]
|
||||
|
||||
|
||||
class TableTag(object):
|
||||
"""
|
||||
Classe mémorisant les moyennes des étudiants à différents tags et permettant de
|
||||
calculer des rangs et des statistiques.
|
||||
|
||||
Ses attributs sont:
|
||||
|
||||
* nom : Nom représentatif des données de la Table
|
||||
* inscrlist : Les étudiants inscrits dans le TagTag avec leur information de la forme :
|
||||
{ etudid : dictionnaire d'info extrait de Scodoc, ...}
|
||||
* taglist : Liste triée des noms des tags
|
||||
* resultats : Dictionnaire donnant les notes-moyennes de chaque étudiant par tag et la somme commulée
|
||||
des coeff utilisées dans le calcul de la moyenne pondérée, sous la forme :
|
||||
{ tag : { etudid: (note_moy, somme_coeff_norm),
|
||||
...}
|
||||
* rangs : Dictionnaire donnant les rang par tag de chaque étudiant de la forme :
|
||||
{ tag : {etudid: rang, ...} }
|
||||
* nbinscrits : Nombre d'inscrits dans le semestre (pas de distinction entre les tags)
|
||||
* statistiques : Dictionnaire donnant les statistiques (moyenne, min, max) des résultats par tag de la forme :
|
||||
{ tag : (moy, min, max), ...}
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, nom: str):
|
||||
"""Les attributs basiques des TagTable, qui seront initialisés
|
||||
dans les classes dérivées
|
||||
def __init__(self):
|
||||
"""Classe centralisant différentes méthodes communes aux
|
||||
SemestreTag, TrajectoireTag, AggregatInterclassTag
|
||||
"""
|
||||
self.nom = nom
|
||||
"""Les étudiants"""
|
||||
self.etudiants = {}
|
||||
"""Les moyennes par tag"""
|
||||
self.moyennes_tags = {}
|
||||
|
||||
pass
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
def get_all_tags(self):
|
||||
@ -90,8 +65,21 @@ class TableTag(object):
|
||||
"""
|
||||
return sorted(self.moyennes_tags.keys())
|
||||
|
||||
def df_moyennes_et_classements(self):
|
||||
"""Renvoie un dataframe listant toutes les moyennes,
|
||||
et les classements des étudiants pour tous les tags
|
||||
"""
|
||||
|
||||
def df_tagtable(self):
|
||||
etudiants = self.etudiants
|
||||
df = pd.DataFrame.from_dict(etudiants, orient="index", columns=["nom"])
|
||||
|
||||
for tag in self.get_all_tags():
|
||||
df = df.join(self.moyennes_tags[tag]["notes"].rename(f"Moy {tag}"))
|
||||
df = df.join(self.moyennes_tags[tag]["classements"].rename(f"Class {tag}"))
|
||||
|
||||
return df
|
||||
|
||||
def df_notes(self):
|
||||
"""Renvoie un dataframe (etudid x tag) listant toutes les moyennes par tags
|
||||
|
||||
Returns:
|
||||
@ -117,4 +105,3 @@ class TableTag(object):
|
||||
df = df.join(self.moyennes_tags[tag]["classements"].rename(f"class {tag}"))
|
||||
|
||||
return df.to_csv(sep=";")
|
||||
|
||||
|
@ -46,16 +46,17 @@ class Trajectoire:
|
||||
"""
|
||||
self.semestres_aggreges = self.semestres_aggreges | semestres
|
||||
|
||||
def get_repr(self):
|
||||
def get_repr(self, verbose=True) -> str:
|
||||
"""Représentation textuelle d'une trajectoire
|
||||
basée sur ses semestres aggrégés"""
|
||||
|
||||
noms = []
|
||||
for fid in self.semestres_aggreges:
|
||||
semestre = self.semestres_aggreges[fid]
|
||||
noms.append(f"S{semestre.semestre_id}({fid})")
|
||||
noms = sorted(noms)
|
||||
repr = f"{self.nom} ({self.semestre_final.formsemestre_id}) {self.semestre_final.date_fin.year}"
|
||||
if noms:
|
||||
if verbose and noms:
|
||||
repr += " - " + "+".join(noms)
|
||||
return repr
|
||||
|
||||
|
@ -47,30 +47,30 @@ from app.pe.pe_tabletags import TableTag
|
||||
|
||||
|
||||
class TrajectoireTag(TableTag):
|
||||
"""Calcule les moyennes par tag d'une combinaison de semestres
|
||||
(trajectoires), identifiée par un nom d'aggrégat (par ex: '3S') et
|
||||
par un semestre terminal, pour extraire les classements par tag pour un
|
||||
groupe d'étudiants donnés. Le groupe d'étudiants est formé par ceux ayant tous
|
||||
participé au semestre terminal.
|
||||
|
||||
Par ex: fusion d'un parcours ['S1', 'S2', 'S3'] donnant un nom_combinaison = '3S'
|
||||
|
||||
"""
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def __init__(
|
||||
self,
|
||||
nom: str,
|
||||
trajectoire: Trajectoire,
|
||||
semestres_taggues: dict[int, SemestreTag]
|
||||
):
|
||||
""" """
|
||||
TableTag.__init__(self, nom=nom)
|
||||
"""Calcule les moyennes par tag d'une combinaison de semestres
|
||||
(trajectoires), identifiée par un nom d'aggrégat (par ex: '3S') et
|
||||
par un semestre terminal, pour extraire les classements par tag pour un
|
||||
groupe d'étudiants donnés. Le groupe d'étudiants est formé par ceux ayant tous
|
||||
participé au semestre terminal.
|
||||
|
||||
"""La trajectoire associée"""
|
||||
Par ex: fusion d'un parcours ['S1', 'S2', 'S3'] donnant un nom_combinaison = '3S'
|
||||
|
||||
"""
|
||||
TableTag.__init__(self)
|
||||
|
||||
# La trajectoire associée
|
||||
self.trajectoire_id = trajectoire.trajectoire_id
|
||||
self.trajectoire = trajectoire
|
||||
|
||||
# Le nom de la trajectoire tagguée (identique à la trajectoire)
|
||||
self.nom = self.get_repr()
|
||||
|
||||
"""Le formsemestre terminal et les semestres aggrégés"""
|
||||
self.formsemestre_terminal = trajectoire.semestre_final
|
||||
nt = load_formsemestre_results(self.formsemestre_terminal)
|
||||
@ -114,10 +114,10 @@ class TrajectoireTag(TableTag):
|
||||
"nb_inscrits": len(moy_gen_tag),
|
||||
}
|
||||
|
||||
def get_repr(self):
|
||||
def get_repr(self, verbose=False) -> str:
|
||||
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
||||
est basée)"""
|
||||
return self.trajectoire.get_repr()
|
||||
return self.trajectoire.get_repr(verbose=verbose)
|
||||
|
||||
def compute_notes_cube(self):
|
||||
"""Construit le cube de notes (etudid x tags x semestre_aggregé)
|
||||
@ -159,8 +159,6 @@ class TrajectoireTag(TableTag):
|
||||
|
||||
return etudids_x_tags_x_semestres
|
||||
|
||||
|
||||
|
||||
def do_taglist(self):
|
||||
"""Synthétise les tags à partir des semestres (taggués) aggrégés
|
||||
|
||||
@ -173,6 +171,8 @@ class TrajectoireTag(TableTag):
|
||||
return sorted(set(tags))
|
||||
|
||||
|
||||
|
||||
|
||||
def compute_tag_moy(set_cube: np.array, etudids: list, tags: list):
|
||||
"""Calcul de la moyenne par tag sur plusieurs semestres.
|
||||
La moyenne est un nombre (note/20), ou NaN si pas de notes disponibles
|
||||
|
Loading…
Reference in New Issue
Block a user