diff --git a/app/comp/moy_mat.py b/app/comp/moy_mat.py index e5ba903c26..0a7522637c 100644 --- a/app/comp/moy_mat.py +++ b/app/comp/moy_mat.py @@ -40,13 +40,11 @@ def compute_mat_moys_classic( modimpl_mask = np.array( [m.module.matiere.id == matiere_id for m in formsemestre.modimpls_sorted] ) - etud_moy_gen, _, _ = moy_ue.compute_ue_moys_classic( - formsemestre, + etud_moy_mat = moy_ue.compute_mat_moys_classic( sem_matrix=sem_matrix, - ues=ues, modimpl_inscr_df=modimpl_inscr_df, modimpl_coefs=modimpl_coefs, modimpl_mask=modimpl_mask, ) - matiere_moy[matiere_id] = etud_moy_gen + matiere_moy[matiere_id] = etud_moy_mat return matiere_moy diff --git a/app/comp/moy_ue.py b/app/comp/moy_ue.py index 563fb3b1d0..efbe7cd349 100644 --- a/app/comp/moy_ue.py +++ b/app/comp/moy_ue.py @@ -294,7 +294,8 @@ def compute_ue_moys_classic( modimpl_coefs: np.array, modimpl_mask: np.array, ) -> tuple[pd.Series, pd.DataFrame, pd.DataFrame]: - """Calcul de la moyenne d'UE en mode classique. + """Calcul de la moyenne d'UE et de la moy. générale en mode classique (DUT, LMD, ...). + La moyenne d'UE est un nombre (note/20), ou NI ou NA ou ERR NI non inscrit à (au moins un) module de cette UE NA pas de notes disponibles @@ -363,7 +364,7 @@ def compute_ue_moys_classic( modimpl_coefs_etuds_no_nan_stacked = np.stack( [modimpl_coefs_etuds_no_nan.T] * nb_ues ) - # nb_ue x nb_etuds x nb_mods : coefs prenant en compte NaN et inscriptions + # nb_ue x nb_etuds x nb_mods : coefs prenant en compte NaN et inscriptions: coefs = (modimpl_coefs_etuds_no_nan_stacked * ue_modules).swapaxes(1, 2) if coefs.dtype == np.object: # arrive sur des tableaux vides coefs = coefs.astype(np.float) @@ -408,6 +409,68 @@ def compute_ue_moys_classic( return etud_moy_gen_s, etud_moy_ue_df, etud_coef_ue_df +def compute_mat_moys_classic( + sem_matrix: np.array, + modimpl_inscr_df: pd.DataFrame, + modimpl_coefs: np.array, + modimpl_mask: np.array, +) -> pd.Series: + """Calcul de la moyenne sur un sous-enemble de modules en formation CLASSIQUE + + La moyenne est un nombre (note/20 ou NaN. + + Le masque modimpl_mask est un tableau de booléens (un par modimpl) qui + permet de sélectionner un sous-ensemble de modules (ceux de la matière d'intérêt). + + sem_matrix: notes moyennes aux modules (tous les étuds x tous les modimpls) + ndarray (etuds x modimpls) + (floats avec des NaN) + etuds : listes des étudiants (dim. 0 de la matrice) + modimpl_inscr_df: matrice d'inscription du semestre (etud x modimpl) + modimpl_coefs: vecteur des coefficients de modules + modimpl_mask: masque des modimpls à prendre en compte + + Résultat: + - moyennes: pd.Series, index etudid + """ + if (not len(modimpl_mask)) or ( + sem_matrix.shape[0] == 0 + ): # aucun module ou aucun étudiant + # etud_moy_gen_s, etud_moy_ue_df, etud_coef_ue_df + return pd.Series( + [0.0] * len(modimpl_inscr_df.index), index=modimpl_inscr_df.index + ) + # Restreint aux modules sélectionnés: + sem_matrix = sem_matrix[:, modimpl_mask] + modimpl_inscr = modimpl_inscr_df.values[:, modimpl_mask] + modimpl_coefs = modimpl_coefs[modimpl_mask] + + nb_etuds, nb_modules = sem_matrix.shape + assert len(modimpl_coefs) == nb_modules + + # Enlève les NaN du numérateur: + sem_matrix_no_nan = np.nan_to_num(sem_matrix, nan=0.0) + # Ne prend pas en compte les notes des étudiants non inscrits au module: + # Annule les notes: + sem_matrix_inscrits = np.where(modimpl_inscr, sem_matrix_no_nan, 0.0) + # Annule les coefs des modules où l'étudiant n'est pas inscrit: + modimpl_coefs_etuds = np.where( + modimpl_inscr, np.stack([modimpl_coefs.T] * nb_etuds), 0.0 + ) + # Annule les coefs des modules NaN (nb_etuds x nb_mods) + modimpl_coefs_etuds_no_nan = np.where( + np.isnan(sem_matrix), 0.0, modimpl_coefs_etuds + ) + if modimpl_coefs_etuds_no_nan.dtype == np.object: # arrive sur des tableaux vides + modimpl_coefs_etuds_no_nan = modimpl_coefs_etuds_no_nan.astype(np.float) + + etud_moy_mat = (modimpl_coefs_etuds_no_nan * sem_matrix_inscrits).sum( + axis=1 + ) / modimpl_coefs_etuds_no_nan.sum(axis=1) + + return pd.Series(etud_moy_mat, index=modimpl_inscr_df.index) + + def compute_malus( formsemestre: FormSemestre, sem_modimpl_moys: np.array,