diff --git a/app/pe/moys/pe_sxtag.py b/app/pe/moys/pe_sxtag.py index 6b148cf53bfbaf52681bda6c33fa466685902911..9efa0327936e876cfd96fb86fe93a0b500b93f82 100644 --- a/app/pe/moys/pe_sxtag.py +++ b/app/pe/moys/pe_sxtag.py @@ -43,37 +43,38 @@ import numpy as np from app.pe.moys import pe_moytag, pe_tabletags import app.pe.rcss.pe_trajectoires as pe_trajectoires -from app.scodoc.sco_utils import ModuleType class SxTag(pe_tabletags.TableTag): - def __init__( - self, - sxtag_id: (str, int), - semx: pe_trajectoires.SemX, - ressembuttags: dict[int, pe_ressemtag.ResSemBUTTag], - ): - """Calcule les moyennes/classements par tag d'un semestre de type 'Sx' - (par ex. 'S1', 'S2', ...) représentés par acronyme d'UE. + """Calcule les moyennes/classements par tag d'un semestre de type 'Sx' + (par ex. 'S1', 'S2', ...) représentés par acronyme d'UE. - Il représente : + Il représente : - * pour les étudiants *non redoublants* : moyennes/classements - du semestre suivi - * pour les étudiants *redoublants* : une fusion des moyennes/classements - dans les (2) 'Sx' qu'il a suivi, en exploitant les informations de capitalisation : - meilleure moyenne entre l'UE capitalisée et l'UE refaite (la notion de meilleure - s'appliquant à la moyenne d'UE) + * pour les étudiants *non redoublants* : moyennes/classements + du semestre suivi + * pour les étudiants *redoublants* : une fusion des moyennes/classements + dans les (2) 'Sx' qu'il a suivi, en exploitant les informations de capitalisation : + meilleure moyenne entre l'UE capitalisée et l'UE refaite (la notion de meilleure + s'appliquant à la moyenne d'UE) - Un SxTag (regroupant potentiellement plusieurs semestres) est identifié - par un tuple ``(Sx, fid)`` où : + Un SxTag (regroupant potentiellement plusieurs semestres) est identifié + par un tuple ``(Sx, fid)`` où : - * ``x`` est le rang (semestre_id) du semestre - * ``fid`` le formsemestre_id du semestre final (le plus récent) du regroupement. + * ``x`` est le rang (semestre_id) du semestre + * ``fid`` le formsemestre_id du semestre final (le plus récent) du regroupement. - Les **tags**, les **UE** et les inscriptions aux UEs (pour les étudiants) - considérés sont uniquement ceux du semestre final. + Les **tags**, les **UE** et les inscriptions aux UEs (pour les étudiants) + considérés sont uniquement ceux du semestre final. + """ + def __init__( + self, + sxtag_id: tuple[str, int], + semx: pe_trajectoires.SemX, + ressembuttags: dict[int, pe_ressemtag.ResSemBUTTag], + ): + """ Args: sxtag_id: L'identifiant de SxTag ressembuttags: Un dictionnaire de la forme `{fid: ResSemBUTTag(fid)}` donnant @@ -84,7 +85,7 @@ class SxTag(pe_tabletags.TableTag): assert sxtag_id and len(sxtag_id) == 2 and sxtag_id[1] in ressembuttags - self.sxtag_id: (str, int) = sxtag_id + self.sxtag_id: tuple[str, int] = sxtag_id """Identifiant du SxTag de la forme (nom_Sx, fid_semestre_final)""" assert ( len(self.sxtag_id) == 2 @@ -183,7 +184,7 @@ class SxTag(pe_tabletags.TableTag): # Moyennes (tous modules confondus) if not self.has_notes_tag(tag): pe_affichage.pe_print( - f" --> Semestre (final) actuellement sans notes" + " --> Semestre (final) actuellement sans notes" ) matrice_moys_ues = pd.DataFrame( np.nan, index=self.etudids_sorted, columns=self.acronymes_sorted @@ -238,7 +239,7 @@ class SxTag(pe_tabletags.TableTag): # affichage = [str(fid) for fid in self.ressembuttags] return f"SXTag {self.agregat}#{self.fid_final}" - def compute_notes_ues_cube(self, tag) -> (pd.DataFrame, np.array): + def compute_notes_ues_cube(self, tag) -> tuple[pd.DataFrame, np.array]: """Construit le cube de notes des UEs (etudid x accronyme_ue x semestre_aggregé) nécessaire au calcul des moyennes du tag pour le RCS Sx. (Renvoie également le dataframe associé pour debug). @@ -281,7 +282,7 @@ class SxTag(pe_tabletags.TableTag): # Stocke le df dfs[frmsem_id] = df - """Réunit les notes sous forme d'un cube etudids x ues x semestres""" + # Réunit les notes sous forme d'un cube etudids x ues x semestres semestres_x_etudids_x_ues = [dfs[fid].values for fid in dfs] etudids_x_ues_x_semestres = np.stack(semestres_x_etudids_x_ues, axis=-1) return dfs, etudids_x_ues_x_semestres @@ -316,14 +317,14 @@ class SxTag(pe_tabletags.TableTag): # assert nb_ues == nb_ues_mask # Entrées à garder dans le cube en fonction du masque d'inscription aux UEs du parcours - inscr_mask_3D = np.stack([inscr_mask] * nb_semestres, axis=-1) - set_cube = set_cube * inscr_mask_3D + inscr_mask_3d = np.stack([inscr_mask] * nb_semestres, axis=-1) + set_cube = set_cube * inscr_mask_3d # Entrées à garder en fonction des UEs capitalisées ou non set_cube = set_cube * masque_cube # 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 : NaN -> -1.0 set_cube_no_nan = np.nan_to_num(set_cube, nan=-1.0) @@ -352,7 +353,7 @@ def compute_masques_capitalisation_cube( acronymes_sorted: list[str], ressembuttags: dict[int, pe_ressemtag.ResSemBUTTag], formsemestre_id_final: int, -) -> (pd.DataFrame, np.array): +) -> tuple[pd.DataFrame, np.array]: """Construit le cube traduisant les masques des UEs à prendre en compte dans le calcul des moyennes, en utilisant le dataFrame de capitalisations de chaque ResSemBUTTag @@ -383,9 +384,12 @@ def compute_masques_capitalisation_cube( else: # semestres redoublés df = pd.DataFrame(0.0, index=etudids_sorted, columns=acronymes_sorted) - # Traitement des capitalisations : remplace les infos de capitalisations par les coeff 1 ou 0 + # Traitement des capitalisations : + # remplace les infos de capitalisations par les coeff 1 ou 0 capitalisations = ressembuttags[frmsem_id].capitalisations - capitalisations = capitalisations.replace(True, 1.0).replace(False, 0.0) + capitalisations = capitalisations.replace({True: 1.0, False: 0.0}).astype( + float + ) # Met à 0 les coeffs des UEs non capitalisées pour les étudiants # inscrits dans les 2 semestres: 1.0*False => 0.0 @@ -400,7 +404,7 @@ def compute_masques_capitalisation_cube( # Stocke le df dfs[frmsem_id] = df - """Réunit les notes sous forme d'un cube etudids x ues x semestres""" + # Réunit les notes sous forme d'un cube etudids x ues x semestres semestres_x_etudids_x_ues = [dfs[fid].values for fid in dfs] etudids_x_ues_x_semestres = np.stack(semestres_x_etudids_x_ues, axis=-1) return dfs, etudids_x_ues_x_semestres diff --git a/app/pe/pe_jury.py b/app/pe/pe_jury.py index f060fdb4c18d961b747bbd8b33fbd070e694146c..0b1bcfbd4f496f0de00fa749b2627ed1f9d84ea7 100644 --- a/app/pe/pe_jury.py +++ b/app/pe/pe_jury.py @@ -101,7 +101,7 @@ class JuryPE(object): def __init__(self, diplome: int, formsemestre_id_base, options: dict | None = None): options = options or {} - for k, y in self._default_options.items(): + for k, v in self._default_options.items(): if k not in options: options[k] = v pe_affichage.pe_start_log() @@ -184,13 +184,13 @@ class JuryPE(object): if self.diplomes_ids: onglet = "diplômés" df_diplome = self.etudiants.df_administratif(self.diplomes_ids) - df_diplome.to_excel(writer, onglet, index=True, header=True) + df_diplome.to_excel(writer, sheet_name=onglet, index=True, header=True) if self.etudiants.abandons_ids: onglet = "redoublants-réorientés" df_abandon = self.etudiants.df_administratif( self.etudiants.abandons_ids ) - df_abandon.to_excel(writer, onglet, index=True, header=True) + df_abandon.to_excel(writer, sheet_name=onglet, index=True, header=True) output.seek(0) self.add_file_to_zip( @@ -248,7 +248,7 @@ class JuryPE(object): # Conversion colonnes en multiindex df = convert_colonnes_to_multiindex(df) # écriture dans l'onglet - df.to_excel(writer, onglet, index=True, header=True) + df.to_excel(writer, sheet_name=onglet, index=True, header=True) pe_affichage.pe_print( f"--> Export excel de {', '.join(onglets)}", info=True ) @@ -340,7 +340,7 @@ class JuryPE(object): df = convert_colonnes_to_multiindex(df) # écriture dans l'onglet - df.to_excel(writer, onglet, index=True, header=True) + df.to_excel(writer, sheet_name=onglet, index=True, header=True) pe_affichage.pe_print( f"--> Export excel de {', '.join(onglets)}", info=True ) @@ -440,7 +440,7 @@ class JuryPE(object): df = convert_colonnes_to_multiindex(df) onglets += ["📊" + onglet] # écriture dans l'onglet - df.to_excel(writer, onglet, index=True, header=True) + df.to_excel(writer, sheet_name=onglet, index=True, header=True) pe_affichage.pe_print( f"--> Export excel de {', '.join(onglets)}", info=True ) @@ -532,7 +532,7 @@ class JuryPE(object): df = convert_colonnes_to_multiindex(df) onglets += [onglet] # écriture dans l'onglet - df.to_excel(writer, onglet, index=True, header=True) + df.to_excel(writer, sheet_name=onglet, index=True, header=True) pe_affichage.pe_print(f"=> Export excel de {', '.join(onglets)}", info=True) output.seek(0) @@ -597,7 +597,9 @@ class JuryPE(object): onglets += [nom_onglet] # écriture dans l'onglet: df_final = df_final.replace("nan", "") - df_final.to_excel(writer, nom_onglet, index=True, header=True) + df_final.to_excel( + writer, sheet_name=nom_onglet, index=True, header=True + ) pe_affichage.pe_print(f"=> Export excel de {', '.join(onglets)}", info=True) output.seek(0) diff --git a/sco_version.py b/sco_version.py index 5be21a47b421291cfa80072b22df4423a4eadf22..d68c1cd04baa2c1755cc99e486e196634429d13f 100644 --- a/sco_version.py +++ b/sco_version.py @@ -3,7 +3,7 @@ "Infos sur version ScoDoc" -SCOVERSION = "9.7.69" +SCOVERSION = "9.7.70" SCONAME = "ScoDoc"