"""Recompute IT05 derived metrics from the analytical CSV; Python 3 standard library. Source extraction is separately auditable via sources.json and the CSV cell references. Author: Alisson Bento. Source: Istat 2025 library census tables, CC BY 4.0. """ from pathlib import Path import csv, json P=Path(__file__).resolve().parent rows=list(csv.DictReader((P/'reading_groups_panel.csv').open(encoding='utf-8',newline=''))) out=[] for r in rows: y,n=float(r['yes_pct']),float(r['no_pct']) out.append(dict(municipality_category=r['municipality_category'],known_status_yes_pct_approx=100*y/(y+n),missing_status_low_pct_approx=y,missing_status_high_pct_approx=100-n)) six=[r for r in rows if r['category']=='size_band'] assert len(six)==6 y=[float(r['yes_pct']) for r in six] assert sum(int(r['public_reading_base_n']) for r in rows if r['category']!='national')==6252 metrics=dict(six_band_availability_range_pp=round(max(y)-min(y),6),six_band_availability_max_min_ratio=max(y)/min(y),ratio_of_printed_means_NOT_exact=4/3,nearest_integer_mean_ratio_upper_bound_assumption=4.5/2.5,nearest_tenth_availability_ratio_lower_bound_assumption=(61.6-.05)/(28.9+.05),smallest_unknown_all_yes_vs_10k_30k_gap_pp_approx=round(61.6-(100-63.5),6)) with (P/'recomputed_sensitivities.csv').open('w',encoding='utf-8',newline='') as f: w=csv.DictWriter(f,fieldnames=list(out[0]),lineterminator='\n');w.writeheader();w.writerows(out) (P/'recomputed_metrics.json').write_text(json.dumps(metrics,indent=2)+'\n',encoding='utf-8') print(json.dumps(metrics,indent=2))