Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
6 changed files with 224 additions and 96 deletions
Showing only changes of commit b8cb592ac9 - Show all commits

View File

@ -50,6 +50,7 @@ from zipfile import ZipFile
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from app.pe import pe_semtag
from app.pe.pe_affichage import NOM_STAT_PROMO, SANS_NOTE, NOM_STAT_GROUPE from app.pe.pe_affichage import NOM_STAT_PROMO, SANS_NOTE, NOM_STAT_GROUPE
import app.pe.pe_affichage as pe_affichage import app.pe.pe_affichage as pe_affichage
from app.pe.pe_etudiant import * # TODO A éviter -> pe_etudiant. from app.pe.pe_etudiant import * # TODO A éviter -> pe_etudiant.
@ -96,7 +97,9 @@ class JuryPE(object):
pe_affichage.pe_print("*** Aucun étudiant diplômé") pe_affichage.pe_print("*** Aucun étudiant diplômé")
else: else:
self._gen_xls_diplomes(zipfile) self._gen_xls_diplomes(zipfile)
self._gen_rcss()
self._gen_xls_resultats_semestres_taggues(zipfile) self._gen_xls_resultats_semestres_taggues(zipfile)
self._gen_xls_semestres_taggues(zipfile)
# self._gen_xls_rcss_tags(zipfile) # self._gen_xls_rcss_tags(zipfile)
# self._gen_xls_interclassements_rcss(zipfile) # self._gen_xls_interclassements_rcss(zipfile)
# self._gen_xls_synthese_jury_par_tag(zipfile) # self._gen_xls_synthese_jury_par_tag(zipfile)
@ -142,12 +145,53 @@ class JuryPE(object):
output, engine="openpyxl" output, engine="openpyxl"
) as writer: ) as writer:
for res_sem_tag in self.res_sems_tags.values(): for res_sem_tag in self.res_sems_tags.values():
onglet = res_sem_tag.get_repr() onglet = res_sem_tag.get_repr(verbose=False)
df = res_sem_tag.df_moyennes_et_classements() df = res_sem_tag.df_moyennes_et_classements()
# écriture dans l'onglet # écriture dans l'onglet
df.to_excel(writer, onglet, index=True, header=True) df.to_excel(writer, onglet, index=True, header=True)
output.seek(0) output.seek(0)
self.add_file_to_zip(
zipfile,
f"resultats_semestres_taggues_{self.diplome}.xlsx",
output.read(),
path="details",
)
def _gen_rcss(self):
"""Génère les RCS (attribut `rcss_jury`), combinaisons de semestres suivis par les étudiants au sens
d'un nom de RCS (par ex: '3S').
"""
pe_affichage.pe_print(
"*** Génère les RCS (différentes combinaisons de semestres) des étudiants"
)
self.rcss_jury = pe_rcs.RCSsJuryPE(self.diplome)
self.rcss_jury.cree_rcss(self.etudiants)
def _gen_xls_semestres_taggues(self, zipfile: ZipFile):
"""Génère les semestres taggués en s'appuyant sur les RCS de type Sx (pour
identifier les redoublements impactant les semestres taggués).
"""
# Génère les moyennes des RCS de type Sx
pe_affichage.pe_print("*** Calcule les moyennes de semestres = RCS de type Sx")
self.sems_tags = {}
for rcs_id, rcs in self.rcss_jury.rcss.items():
if rcs.nom.startswith("S"):
self.sems_tags[rcs_id] = pe_semtag.SemTag(rcs, self.res_sems_tags)
# Intègre le bilan des semestres taggués au zip final
output = io.BytesIO()
with pd.ExcelWriter( # pylint: disable=abstract-class-instantiated
output, engine="openpyxl"
) as writer:
for sem_tag in self.sems_tags.values():
onglet = sem_tag.get_repr(verbose=False)
df = sem_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( self.add_file_to_zip(
zipfile, zipfile,
f"semestres_taggues_{self.diplome}.xlsx", f"semestres_taggues_{self.diplome}.xlsx",
@ -156,11 +200,7 @@ class JuryPE(object):
) )
def _gen_xls_rcss_tags(self, zipfile: ZipFile): def _gen_xls_rcss_tags(self, zipfile: ZipFile):
"""Génère : """Génère les RCS tagguées des RCS, en calculant les moyennes et les classements par tag
* les RCS (combinaisons de semestres suivis par les étudiants au sens
d'un aggrégat (par ex: '3S'))
* les RCS tagguées des RCS, en calculant les moyennes et les classements par tag
pour chacune. pour chacune.
Stocke le résultat dans self.rccs_tag, un dictionnaire de Stocke le résultat dans self.rccs_tag, un dictionnaire de
@ -183,14 +223,9 @@ class JuryPE(object):
""" """
pe_affichage.pe_print(
"*** Génère les trajectoires (différentes combinaisons de semestres) des étudiants"
)
self.rcss_jury = pe_rcs.RCSsJuryPE(self.diplome)
self.rcss_jury.cree_rcss(self.etudiants)
# Génère les moyennes par tags des trajectoires # Génère les moyennes des RCS de type Sx
pe_affichage.pe_print("*** Calcule les moyennes par tag des RCS possibles") pe_affichage.pe_print("*** Calcule les moyennes des RCS de type Sx")
self.rcss_tags = {} self.rcss_tags = {}
for rcs_id, rcs in self.rcss_jury.rcss.items(): for rcs_id, rcs in self.rcss_jury.rcss.items():
@ -597,9 +632,6 @@ def compute_resultats_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
return semestres_tags return semestres_tags
def compute_interclassements( def compute_interclassements(
etudiants: EtudiantsJuryPE, etudiants: EtudiantsJuryPE,
trajectoires_jury_pe: pe_rcs.RCSsJuryPE, trajectoires_jury_pe: pe_rcs.RCSsJuryPE,

View File

@ -1,9 +1,11 @@
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from app import comp
from app.comp.moy_sem import comp_ranks_series from app.comp.moy_sem import comp_ranks_series
from app.models import UniteEns from app.models import UniteEns
from app.pe import pe_affichage from app.pe import pe_affichage
from app.scodoc.codes_cursus import UE_SPORT
class Moyenne: class Moyenne:
@ -157,8 +159,9 @@ class MoyennesTag:
def __init__( def __init__(
self, self,
tag: str, tag: str,
ues: list[UniteEns], ues: dict[int, UniteEns],
notes_ues: pd.DataFrame, notes_ues: pd.DataFrame,
ues_inscr_parcours_df: pd.DataFrame
# notes_gen: pd.Series, # notes_gen: pd.Series,
): ):
"""Classe centralisant la synthèse des moyennes/classements d'une série """Classe centralisant la synthèse des moyennes/classements d'une série
@ -169,21 +172,39 @@ class MoyennesTag:
tag: Un tag tag: Un tag
ues: La liste des UEs ayant servie au calcul de la moyenne ues: La liste des UEs ayant servie au calcul de la moyenne
notes_ues: Les moyennes (etudid x acronymes_ues) aux différentes UEs et pour le tag notes_ues: Les moyennes (etudid x acronymes_ues) aux différentes UEs et pour le tag
ues_inscr_parcours_df: Les inscriptions des etudid au UE
# notes_gen: Une série de notes (moyenne) sous forme d'un pd.Series() (toutes UEs confondues) # notes_gen: Une série de notes (moyenne) sous forme d'un pd.Series() (toutes UEs confondues)
""" """
self.tag = tag self.tag = tag
"""Le tag associé aux moyennes""" """Le tag associé aux moyennes"""
# Les UE # Les UE
self.ues: dict[int, UniteEns] = {ue.id: ue for ue in ues} self.ues: dict[int, UniteEns] = ues
"""Les UEs sur lesquelles sont calculées les moyennes""" """Les UEs sur lesquelles sont calculées les moyennes"""
colonnes = list(notes_ues.columns) colonnes = list(notes_ues.columns)
acronymes = [self.ues[ue_id].acronyme for ue_id in colonnes] acronymes: list[str] = [self.ues[ue_id].acronyme for ue_id in self.ues]
assert len(set(acronymes)) == len(colonnes), \ assert len(set(acronymes)) == len(
"Deux UEs ne peuvent pas avoir le même acronyme" colonnes
), "Deux UEs ne peuvent pas avoir le même acronyme"
# Les inscriptions des etudids aux UEs
self.ues_inscr_parcours_df: pd.DataFrame = ues_inscr_parcours_df
"""Les inscriptions des etudids au UE en fonction de leur parcours"""
# Les coefficients à appliquer aux UEs pour la moyenne générale = ECTS
self.ects = self.ues_inscr_parcours_df.fillna(0.0) * [
ue.ects
for ue in self.ues.values() # if ue.type != UE_SPORT <= déjà supprimé
]
# Les profils d'ects (pour debug)
profils_ects = []
for val in list(self.ects.values):
if tuple(val) not in profils_ects:
profils_ects.append(tuple(val))
# Les moyennes par UE # Les moyennes par UE
self.notes_ues = notes_ues self.notes_ues: pd.DataFrame = notes_ues
"""Les notes aux UEs (dataframe)""" """Les notes aux UEs (dataframe)"""
self.notes_ues.columns = acronymes # remplace les ue.id par leur acronyme self.notes_ues.columns = acronymes # remplace les ue.id par leur acronyme
self.moys_ues: dict[int, pd.DataFrame] = {} self.moys_ues: dict[int, pd.DataFrame] = {}
@ -193,11 +214,42 @@ class MoyennesTag:
self.moys_ues[ue.acronyme] = Moyenne(notes) self.moys_ues[ue.acronyme] = Moyenne(notes)
# Les moyennes générales # Les moyennes générales
notes_gen = self.compute_moy_gen(self.notes_ues, self.ects)
self.notes_gen = notes_gen self.notes_gen = notes_gen
"""Les notes générales (moyenne toutes UEs confonudes)""" """Les notes générales (moyenne toutes UEs confonudes)"""
self.moy_gen = Moyenne(notes_gen) self.moy_gen = Moyenne(notes_gen)
"""Le dataframe retraçant les moyennes/classements/statistiques général""" """Le dataframe retraçant les moyennes/classements/statistiques général"""
pe_affichage.pe_print(f"> MoyTag pour {tag} avec")
pe_affichage.pe_print(f" - ues={acronymes}")
pe_affichage.pe_print(f" - ects={profils_ects}")
def __eq__(self, other): def __eq__(self, other):
"""Egalité de deux MoyenneTag lorsque leur tag sont identiques""" """Egalité de deux MoyenneTag lorsque leur tag sont identiques"""
return self.tag == other.tag return self.tag == other.tag
def compute_moy_gen(
self, moy_ues: pd.DataFrame, coeff_ues: pd.DataFrame
) -> pd.Series:
"""Calcule la moyenne générale (toutes UE confondus)
pour le tag considéré, en pondérant les notes obtenues au UE
par les crédits ECTS.
Args:
moy_ues: Les moyennes etudids x acronymes_ues
coeff_ues: Les coeff etudids x ueids
"""
# Calcule la moyenne générale dans le semestre (pondérée par le ECTS)
try:
moy_gen_tag = comp.moy_sem.compute_sem_moys_apc_using_ects(
moy_ues,
coeff_ues,
# formation_id=self.formsemestre.formation_id,
skip_empty_ues=True,
)
except TypeError as e:
raise TypeError("Pb dans le calcul de la moyenne toutes UEs confondues")
return moy_gen_tag

View File

@ -94,7 +94,7 @@ class RCSTag(TableTag):
self.etuds = nt.etuds self.etuds = nt.etuds
# assert self.etuds == trajectoire.suivi # manque-t-il des étudiants ? # assert self.etuds == trajectoire.suivi # manque-t-il des étudiants ?
self.etudiants = {etud.etudid: etud.etat_civil for etud in self.etuds} self.etats_civils = {etud.etudid: etud.nomprenom for etud in self.etuds}
self.tags_sorted = self.do_taglist() self.tags_sorted = self.do_taglist()
"""Tags extraits de tous les semestres""" """Tags extraits de tous les semestres"""
@ -102,7 +102,7 @@ class RCSTag(TableTag):
self.notes_cube = self.compute_notes_cube() self.notes_cube = self.compute_notes_cube()
"""Cube de notes""" """Cube de notes"""
etudids = list(self.etudiants.keys()) etudids = list(self.etats_civils.keys())
self.notes = compute_tag_moy(self.notes_cube, etudids, self.tags_sorted) self.notes = compute_tag_moy(self.notes_cube, etudids, self.tags_sorted)
"""Calcul les moyennes par tag sous forme d'un dataframe""" """Calcul les moyennes par tag sous forme d'un dataframe"""

View File

@ -70,19 +70,15 @@ class ResSemTag(TableTag):
self.formsemestre = FormSemestre.get_formsemestre(formsemestre_id) self.formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
# Le nom du res_semestre taggué # Le nom du res_semestre taggué
self.nom = self.get_repr(mode="long") self.nom = self.get_repr(verbose=True)
pe_affichage.pe_print( pe_affichage.pe_print(f"--> Résultats de semestre taggués {self.nom}")
f"--> Résultats de Semestre taggués {self.nom}"
)
# Les résultats du semestre # Les résultats du semestre
self.nt = load_formsemestre_results(self.formsemestre) self.nt = load_formsemestre_results(self.formsemestre)
# Les étudiants # Les étudiants (etuds, états civils & etudis)
self.etuds = self.nt.etuds self.add_etuds(self.nt.etuds)
self.etudiants = {etud.etudid: etud.etat_civil for etud in self.etuds}
self.etudids = list(self.etudiants.keys())
# Les notes, les modules implémentés triés, les étudiants, les coeffs, # Les notes, les modules implémentés triés, les étudiants, les coeffs,
# récupérés notamment de py:mod:`res_but` # récupérés notamment de py:mod:`res_but`
@ -113,8 +109,13 @@ class ResSemTag(TableTag):
moy_ues_tag = self.compute_moy_ues_tag(infos_tag) moy_ues_tag = self.compute_moy_ues_tag(infos_tag)
# moy_gen_tag = self.compute_moy_gen_tag(moy_ues_tag) # moy_gen_tag = self.compute_moy_gen_tag(moy_ues_tag)
ues_dict = {ue.id: ue for ue in ues_hors_sport}
self.moyennes_tags[tag] = MoyennesTag( self.moyennes_tags[tag] = MoyennesTag(
tag, ues_hors_sport, moy_ues_tag # moy_gen_tag tag,
ues_dict,
moy_ues_tag,
self.ues_inscr_parcours_df
# moy_gen_tag
) )
# Ajoute les d'UE moyennes générales de BUT pour le semestre considéré # Ajoute les d'UE moyennes générales de BUT pour le semestre considéré
@ -128,8 +129,10 @@ class ResSemTag(TableTag):
) )
# moy_ues = self.nt.etud_moy_ue[ue_id] # moy_ues = self.nt.etud_moy_ue[ue_id]
# moy_gen_but = self.nt.etud_moy_gen # moy_gen_but = self.nt.etud_moy_gen
ues_dict = {ue.id: ue for ue in ues_hors_sport}
self.moyennes_tags["but"] = MoyennesTag( self.moyennes_tags["but"] = MoyennesTag(
"but", ues_hors_sport, df_ues #, moy_gen_but "but", ues_dict, df_ues, self.ues_inscr_parcours_df # , moy_gen_but
) )
self.tags_sorted = self.get_all_tags() self.tags_sorted = self.get_all_tags()
@ -144,11 +147,11 @@ class ResSemTag(TableTag):
# f" => Traitement des tags {', '.join(self.tags_sorted)}" # f" => Traitement des tags {', '.join(self.tags_sorted)}"
# ) # )
def get_repr(self, mode="long"): def get_repr(self, verbose=False):
"""Nom affiché pour le semestre taggué""" """Nom affiché pour le semestre taggué"""
if mode == "short": if verbose:
return f"{self.formsemestre} ({self.formsemestre_id})" return f"{self.formsemestre} ({self.formsemestre_id})"
else: # mode == "long" else:
return pe_etudiant.nom_semestre_etape(self.formsemestre, avec_fid=True) return pe_etudiant.nom_semestre_etape(self.formsemestre, avec_fid=True)
def compute_moy_ues_tag(self, info_tag: dict[int, dict]) -> pd.DataFrame: def compute_moy_ues_tag(self, info_tag: dict[int, dict]) -> pd.DataFrame:
@ -192,25 +195,6 @@ class ResSemTag(TableTag):
) )
return moyennes_ues_tag return moyennes_ues_tag
def compute_moy_gen_tag(self, moy_ues_tag: pd.DataFrame) -> pd.Series:
"""Calcule la moyenne générale (toutes UE confondus)
pour le tag considéré, en les pondérant par les crédits ECTS.
"""
# Les ects
ects = self.ues_inscr_parcours_df.fillna(0.0) * [
ue.ects for ue in self.ues if ue.type != UE_SPORT
]
# Calcule la moyenne générale dans le semestre (pondérée par le ECTS)
moy_gen_tag = comp.moy_sem.compute_sem_moys_apc_using_ects(
moy_ues_tag,
ects,
formation_id=self.formsemestre.formation_id,
skip_empty_ues=True,
)
return moy_gen_tag
def _get_tags_dict(self): def _get_tags_dict(self):
"""Renvoie les tags personnalisés (déduits des modules du semestre) """Renvoie les tags personnalisés (déduits des modules du semestre)
et les tags automatiques ('but'), et toutes leurs informations, et les tags automatiques ('but'), et toutes leurs informations,
@ -272,8 +256,6 @@ class ResSemTag(TableTag):
raise ScoValueError(message) raise ScoValueError(message)
def get_moduleimpl(modimpl_id) -> dict: def get_moduleimpl(modimpl_id) -> dict:
"""Renvoie l'objet modimpl dont l'id est modimpl_id""" """Renvoie l'objet modimpl dont l'id est modimpl_id"""
modimpl = db.session.get(ModuleImpl, modimpl_id) modimpl = db.session.get(ModuleImpl, modimpl_id)

View File

@ -49,7 +49,7 @@ from app.pe.pe_moytag import MoyennesTag
class SemTag(TableTag): class SemTag(TableTag):
def __init__(self, rcs: RCS, semestres_taggues: dict[int, ResSemTag]): def __init__(self, rcs: RCS, res_sems_tags: dict[int, ResSemTag]):
"""Calcule les moyennes/classements par tag à un RCS d'un seul semestre """Calcule les moyennes/classements par tag à un RCS d'un seul semestre
(ici semestre) de type 'Sx' (par ex. 'S1', 'S2', ...) : (ici semestre) de type 'Sx' (par ex. 'S1', 'S2', ...) :
@ -62,7 +62,7 @@ class SemTag(TableTag):
Args: Args:
rcs: Un RCS (identifié par un nom et l'id de son semestre terminal) rcs: Un RCS (identifié par un nom et l'id de son semestre terminal)
semestres_taggues: Les données sur les semestres taggués res_sems_tags: Les données sur les résultats des semestres taggués
""" """
TableTag.__init__(self) TableTag.__init__(self)
@ -88,27 +88,20 @@ class SemTag(TableTag):
self.semestres_aggreges = rcs.semestres_aggreges self.semestres_aggreges = rcs.semestres_aggreges
"""Les semestres aggrégés""" """Les semestres aggrégés"""
self.semestres_tags_aggreges = {} self.res_sems_tags = {}
"""Les semestres tags associés aux semestres aggrégés""" """Les résultats des semestres taggués (limités aux semestres aggrégés)"""
try: try:
for frmsem_id in self.semestres_aggreges: for frmsem_id in self.semestres_aggreges:
self.semestres_tags_aggreges[frmsem_id] = semestres_taggues[frmsem_id] self.res_sems_tags[frmsem_id] = res_sems_tags[frmsem_id]
except: except:
raise ValueError("Semestres taggués manquants") raise ValueError("Résultats des semestres taggués manquants")
# Les données des étudiants # Les étudiants (etuds, états civils & etudis)
self.etuds = nt.etuds self.add_etuds(nt.etuds)
"""Les étudiants"""
self.etudids = [etud.etudid for etud in self.etuds]
"""Les etudids"""
self.etats_civils = {
etudid: self.etuds[etudid].etat_civil for etudid in self.etudids
}
"""Les états civils"""
# Les tags # Les tags
self.tags_sorted = self.comp_tags_list() self.tags_sorted = self.comp_tags_list()
"""Tags extraits du semestre terminal de l'aggrégat""" """Tags (extraits uniquement du semestre terminal de l'aggrégat)"""
# Les UEs # Les UEs
self.ues = self.comp_ues(tag="but") self.ues = self.comp_ues(tag="but")
@ -116,20 +109,33 @@ class SemTag(TableTag):
"""UEs extraites du semestre terminal de l'aggrégat (avec """UEs extraites du semestre terminal de l'aggrégat (avec
check de concordance sur les UE des semestres_aggrégés)""" check de concordance sur les UE des semestres_aggrégés)"""
# Les inscriptions aux UEs
self.ues_inscr_parcours_df = self.comp_ues_inscr_parcours(tag="but")
"""Les inscriptions aux UEs (extraites uniquement du semestre terminal)"""
self.moyennes_tags: dict[str, MoyennesTag] = {} self.moyennes_tags: dict[str, MoyennesTag] = {}
"""Moyennes/classements par tag (qu'ils soient personnalisés ou automatiques)""" """Moyennes/classements par tag (qu'ils soient personnalisés ou automatiques)"""
self.notes: dict[str, pd.DataFrame] = {} self.moyennes_tags: dict[str, pd.DataFrame] = {}
"""Les notes aux différents tags""" """Les notes aux UEs dans différents tags"""
# Masque des inscriptions
inscr_mask = self.ues_inscr_parcours_df.to_numpy()
for tag in self.tags_sorted: for tag in self.tags_sorted:
# Cube de note # Cube de note
notes_cube = self.compute_notes_ues_cube(tag, self.acronymes_ues) notes_cube = self.compute_notes_ues_cube(tag, self.acronymes_ues_sorted)
# Calcule des moyennes sous forme d'un dataframe""" # Calcule des moyennes sous forme d'un dataframe"""
self.notes[tag] = compute_notes_ues(notes_cube, self.etudids, self.acronymes_ues) moys_ues = compute_notes_ues(
notes_cube,
self.etudids,
self.acronymes_ues_sorted,
inscr_mask,
)
# Les moyennes # Les moyennes
self.moyennes_tags[tag] = MoyennesTag(tag, self.notes[tag]) self.moyennes_tags[tag] = MoyennesTag(tag,
self.ues,
moys_ues,
self.ues_inscr_parcours_df)
def __eq__(self, other): def __eq__(self, other):
"""Egalité de 2 RCS taggués sur la base de leur identifiant""" """Egalité de 2 RCS taggués sur la base de leur identifiant"""
@ -147,7 +153,7 @@ class SemTag(TableTag):
# Index du cube (etudids -> dim 0, ues -> dim 1, semestres -> dim2) # Index du cube (etudids -> dim 0, ues -> dim 1, semestres -> dim2)
etudids = [etud.etudid for etud in self.etuds] etudids = [etud.etudid for etud in self.etuds]
# acronymes_ues = sorted([ue.acronyme for ue in self.ues.values()]) # acronymes_ues = sorted([ue.acronyme for ue in self.ues.values()])
semestres_id = list(self.semestres_tags_aggreges.keys()) semestres_id = list(self.res_sems_tags.keys())
dfs = {} dfs = {}
@ -156,10 +162,12 @@ class SemTag(TableTag):
df = pd.DataFrame(np.nan, index=etudids, columns=acronymes_ues_sorted) df = pd.DataFrame(np.nan, index=etudids, columns=acronymes_ues_sorted)
# Charge les notes du semestre tag # Charge les notes du semestre tag
sem_tag = self.semestres_tags_aggreges[frmsem_id] sem_tag = self.res_sems_tags[frmsem_id]
moys_tag = sem_tag.moyennes_tags[tag] moys_tag = sem_tag.moyennes_tags[tag]
notes = moys_tag.notes_ues # dataframe etudids x ues notes = moys_tag.notes_ues # dataframe etudids x ues
acronymes_ues_sem = list(notes.columns) # les acronymes des UEs du semestre tag acronymes_ues_sem = list(
notes.columns
) # les acronymes des UEs du semestre tag
# UEs communes à celles du SemTag (celles du dernier semestre du RCS) # UEs communes à celles du SemTag (celles du dernier semestre du RCS)
ues_communes = list(set(acronymes_ues_sorted) & set(acronymes_ues_sem)) ues_communes = list(set(acronymes_ues_sorted) & set(acronymes_ues_sem))
@ -168,7 +176,9 @@ class SemTag(TableTag):
etudids_communs = df.index.intersection(notes.index) etudids_communs = df.index.intersection(notes.index)
# Recopie # Recopie
df.loc[etudids_communs, ues_communes] = notes.loc[etudids_communs, ues_communes] df.loc[etudids_communs, ues_communes] = notes.loc[
etudids_communs, ues_communes
]
# Supprime tout ce qui n'est pas numérique # Supprime tout ce qui n'est pas numérique
for col in df.columns: for col in df.columns:
@ -182,7 +192,7 @@ class SemTag(TableTag):
etudids_x_ues_x_semestres = np.stack(semestres_x_etudids_x_ues, axis=-1) etudids_x_ues_x_semestres = np.stack(semestres_x_etudids_x_ues, axis=-1)
return etudids_x_ues_x_semestres return etudids_x_ues_x_semestres
def comp_tags_list(self): def comp_tags_list(self) -> list[str]:
"""Récupère les tag du semestre taggué associé au semestre final du RCS """Récupère les tag du semestre taggué associé au semestre final du RCS
Returns: Returns:
@ -190,7 +200,7 @@ class SemTag(TableTag):
""" """
tags = [] tags = []
dernier_frmid = self.formsemestre_terminal.formsemestre_id dernier_frmid = self.formsemestre_terminal.formsemestre_id
dernier_semestre_tag = self.semestres_tags_aggreges[dernier_frmid] dernier_semestre_tag = self.res_sems_tags[dernier_frmid]
tags = dernier_semestre_tag.tags_sorted tags = dernier_semestre_tag.tags_sorted
pe_affichage.pe_print(f"* Tags : {', '.join(tags)}") pe_affichage.pe_print(f"* Tags : {', '.join(tags)}")
return tags return tags
@ -203,12 +213,29 @@ class SemTag(TableTag):
Un dictionnaire donnant les UEs Un dictionnaire donnant les UEs
""" """
dernier_frmid = self.formsemestre_terminal.formsemestre_id dernier_frmid = self.formsemestre_terminal.formsemestre_id
dernier_semestre_tag = self.semestres_tags_aggreges[dernier_frmid] dernier_semestre_tag = self.res_sems_tags[dernier_frmid]
moy_tag = dernier_semestre_tag.moyennes_tags[tag] moy_tag = dernier_semestre_tag.moyennes_tags[tag]
return moy_tag.ues # les UEs return moy_tag.ues # les UEs
def comp_ues_inscr_parcours(self, tag="but") -> pd.DataFrame:
"""Récupère les informations d'inscription des étudiants aux UEs : ne
conserve que les UEs du semestre terminal (pour les redoublants)
def compute_notes_ues(set_cube: np.array, etudids: list, acronymes_ues: list): Returns:
Un dataFrame etudids x UE indiquant si un étudiant est inscrit à une UE
"""
dernier_frmid = self.formsemestre_terminal.formsemestre_id
dernier_semestre_tag = self.res_sems_tags[dernier_frmid]
moy_tag = dernier_semestre_tag.moyennes_tags[tag]
return moy_tag.ues_inscr_parcours_df
def compute_notes_ues(
set_cube: np.array,
etudids: list,
acronymes_ues: list,
inscr_mask: np.array,
):
"""Calcule la moyenne par UEs à un tag donné en prenant la note maximum (UE """Calcule la moyenne par UEs à un tag donné en prenant la note maximum (UE
par UE) obtenue par un étudiant à un semestre. par UE) obtenue par un étudiant à un semestre.
@ -217,18 +244,27 @@ def compute_notes_ues(set_cube: np.array, etudids: list, acronymes_ues: list):
(semestre_ids x etudids x UEs), des floats avec des NaN (semestre_ids x etudids x UEs), des floats avec des NaN
etudids: liste des étudiants (dim. 0 du cube) etudids: liste des étudiants (dim. 0 du cube)
acronymes_ues: liste des acronymes des ues (dim. 1 du cube) acronymes_ues: liste des acronymes des ues (dim. 1 du cube)
inscr_mask: masque etudids x UE traduisant les inscriptions des
étudiants aux UE (du semestre terminal)
Returns: Returns:
Un DataFrame avec pour columns les moyennes par ues, Un DataFrame avec pour columns les moyennes par ues,
et pour rows les etudid et pour rows les etudid
""" """
nb_etuds, nb_ues, nb_semestres = set_cube.shape nb_etuds, nb_ues, nb_semestres = set_cube.shape
nb_etuds_mask, nb_ues_mask = inscr_mask.shape
assert nb_etuds == len(etudids) assert nb_etuds == len(etudids)
assert nb_ues == len(acronymes_ues) assert nb_ues == len(acronymes_ues)
assert nb_etuds == nb_etuds_mask
assert nb_ues == nb_ues_mask
# Quelles entrées du cube contiennent des notes ? # Quelles entrées du cube contiennent des notes ?
mask = ~np.isnan(set_cube) mask = ~np.isnan(set_cube)
# Enlève les NaN du cube pour les entrées manquantes # Entrées à garder dans le cube en fonction du mask d'inscription
inscr_mask_3D = np.stack([inscr_mask]*nb_semestres, axis=-1)
set_cube = set_cube*inscr_mask_3D
# Enlève les NaN du cube pour les entrées manquantes : NaN -> -1.0
set_cube_no_nan = np.nan_to_num(set_cube, nan=-1.0) set_cube_no_nan = np.nan_to_num(set_cube, nan=-1.0)
# Les moyennes par ues # Les moyennes par ues

View File

@ -39,6 +39,8 @@ Created on Thu Sep 8 09:36:33 2016
import pandas as pd import pandas as pd
from app.models import Identite
TAGS_RESERVES = ["but"] TAGS_RESERVES = ["but"]
@ -47,7 +49,23 @@ class TableTag(object):
"""Classe centralisant différentes méthodes communes aux """Classe centralisant différentes méthodes communes aux
SemestreTag, TrajectoireTag, AggregatInterclassTag SemestreTag, TrajectoireTag, AggregatInterclassTag
""" """
pass # Les étudiants
self.etuds: list[Identite] = None # A venir
"""Les étudiants"""
self.etats_civils: dict[int, Identite] = None
"""Les états civils"""
self.etudids: list[int] = None
"""Les etudids"""
def add_etuds(self, etuds: list[Identite]):
"""Mémorise les informations sur les étudiants
Args:
etuds: la liste des identités de l'étudiant
"""
self.etuds = etuds
self.etats_civils = {etud.etudid: etud.etat_civil for etud in self.etuds}
self.etudids = list(self.etats_civils.keys())
def get_all_tags(self): def get_all_tags(self):
"""Liste des tags de la table, triée par ordre alphabétique, """Liste des tags de la table, triée par ordre alphabétique,
@ -70,15 +88,23 @@ class TableTag(object):
Le dataframe des notes et des classements Le dataframe des notes et des classements
""" """
etudiants = self.etudiants etudiants = self.etats_civils
df = pd.DataFrame.from_dict(etudiants, orient="index", columns=["nom"]) df = pd.DataFrame.from_dict(etudiants, orient="index", columns=["nom"])
tags_tries = self.get_all_tags() tags_tries = self.get_all_tags()
for tag in tags_tries: for tag in tags_tries:
moy_tag = self.moyennes_tags[tag] moy_tag = self.moyennes_tags[tag]
for acronyme in moy_tag.moys_ues:
moy = moy_tag.moys_ues[acronyme] # une moyenne
df = df.join(moy.synthese["notes"].rename(f"Moy {tag}-{acronyme}"))
df = df.join(
moy.synthese["classements"].rename(f"Class {tag}-{acronyme}")
)
moy_gen = moy_tag.moy_gen moy_gen = moy_tag.moy_gen
df = df.join(moy_gen.synthese["notes"].rename(f"Moy {tag}")) df = df.join(moy_gen.synthese["notes"].rename(f"Moy {tag} (gen)"))
df = df.join(moy_gen.synthese["classements"].rename(f"Class {tag}")) df = df.join(moy_gen.synthese["classements"].rename(f"Class {tag} (gen)"))
df.sort_values(by=['nom'])
return df return df