SPB Git
3.6 KB · 63 lines python
1#!/usr/bin/env python32"""Figures ch11 — (1) fiche d'état du sujet du cas 1 : fraction de vie utile consommée a_eff/L par composante, colorée par3note d'état, taille ∝ coût neuf ; (2) sensibilité de la dépréciation physique totale à λ et à la note d'état de la structure.4DONNÉES SYNTHÉTIQUES (cas 1, graine 20261031 ; constats d'inspection fictifs de analysis/python/cases/ch11_inspection.py).5Sorties : assets/figures/ch11/ch11-fig-fiche-etat.pdf, assets/figures/ch11/ch11-fig-sensibilite-age-effectif.pdf"""6import sys, pathlib7ROOT = pathlib.Path(__file__).resolve().parents[3]8sys.path.insert(0, str(ROOT / "analysis/python")); sys.path.insert(0, str(ROOT / "analysis/python/cases"))9import numpy as np10import matplotlib.pyplot as plt11from traite.style import setup, palette, savefig, LARGEUR, fmt_dollars12import ch11_inspection as cas1314COUL_ETAT = {1: palette.cat[4], 2: palette.cat[0], 3: palette.cat[2], 4: palette.cat[1], 5: palette.cat[3]}151617def fiche_etat(f):18    fig, ax = plt.subplots(figsize=(LARGEUR, 4.2))19    f = f.sort_values("ratio", ascending=True).reset_index(drop=True)20    y = np.arange(len(f))21    ax.hlines(y, f["age"] / f["vie_utile"], f["ratio"], color=palette.grid, lw=1.2, zorder=1)22    ax.scatter(f["age"] / f["vie_utile"], y, marker="|", s=60, color=palette.ink2, zorder=2, label="âge chronologique / vie utile")23    tailles = 18 + 220 * f["cout_neuf"] / f["cout_neuf"].max()24    for e in sorted(f["etat"].unique()):25        m = f["etat"] == e26        ax.scatter(f.loc[m, "ratio"], y[m], s=tailles[m], color=COUL_ETAT[int(e)], edgecolor=palette.ink2, lw=0.4, zorder=3, label=f"état {int(e)}")27    ax.set_yticks(y); ax.set_yticklabels([c.replace(" (", "\n(") if len(c) > 44 else c for c in f["composante"]], fontsize=7)28    ax.set_xlim(0, 1.45); ax.axvline(1.0, color=palette.ink2, lw=0.7, ls="--")29    ax.set_xlabel("Fraction de la vie utile consommée\n(trait : âge chronologique ; disque : âge effectif, taille selon le coût neuf)", fontsize=7.5)30    ax.grid(axis="y", visible=False)31    ax.legend(loc="upper left", bbox_to_anchor=(0.01, 0.99), fontsize=6.8, ncol=1, title="Note d'état constatée", title_fontsize=7)32    fig.tight_layout()33    return savefig(fig, "ch11/ch11-fig-fiche-etat.pdf")343536def sensibilite(sens, cn):37    fig, ax = plt.subplots(figsize=(LARGEUR, 3.0))38    for i, e in enumerate(sorted(sens["etat_structure"].unique())):39        s = sens[sens["etat_structure"] == e].sort_values("lambda")40        ax.plot(s["lambda"], s["taux"] * 100, marker="o", ms=4, color=palette.cat[i], label=f"structure en état {int(e)}")41    base = sens[(sens["lambda"] == cas.LAMBDA) & (sens["etat_structure"] == 3)]["taux"].iloc[0] * 10042    ax.plot([cas.LAMBDA], [base], marker="*", ms=11, color=palette.brand, ls="none", zorder=5)43    ax.annotate(f"convention retenue : λ = {cas.LAMBDA}, état 3 → {base:.1f} %", (cas.LAMBDA, base), xytext=(0.52, 40), fontsize=7.5,44                arrowprops=dict(arrowstyle="-", color=palette.ink2, lw=0.7))45    ax.set_xlabel("Poids λ de la note d'état dans l'âge effectif (0 = âge chronologique seul ; 1 = note d'état seule)")46    ax.set_ylabel("Dépréciation physique totale (% du coût neuf)")47    ax.set_xticks([0, 0.25, 0.5, 0.75, 1.0]); ax.set_ylim(20, 72)48    ax.legend(fontsize=7, ncol=3, loc="lower left")49    fig.tight_layout()50    return savefig(fig, "ch11/ch11-fig-sensibilite-age-effectif.pdf")515253def main():54    setup()55    devis, sujet, cn = cas.charger()56    f = cas.fiche(devis, cn); trav = cas.travaux(devis, cn)57    print("OK", fiche_etat(f))58    print("OK", sensibilite(cas.sensibilite(f, trav, cn), cn))596061if __name__ == "__main__":62    main()63
Files · 2eb2bf4e67f754808bae5090a9e53eab37149ddb
Menu

Theme