# Evidence Lab source-script package

These files let readers inspect how the Evidence Lab's numerical reports and
figures were produced. Start with the report's entry point below; its header
explains the question, population, inputs, outputs, and main calculation steps.
Download the shared helpers too, not just the linked entry point.

## What each file does

| # | File | Question or role |
| --- | --- | --- |
| 1 | `report_income_education_joint_model.py` | How do adult BA+ and income or enrolled-student poverty jointly relate to proficiency? |
| 2 | `report_income_education_attendance_joint_model.py` | What happens when tested-grade regular attendance is added? |
| 3 | `report_income_education_attendance_interactions.py` | Do pairwise interactions improve held-out prediction over the additive model? |
| 4 | `report_income_education_split_stability.py` | How stable are coefficients across random halves of the school sample? |
| 5 | `report_income_poverty_reassessment.py` | Compare income, poverty, and combined models, with explicit missingness and poverty-interval sensitivities. |
| 6 | `report_ba_signal_in_high_poverty.py` | Describe BA+ associations within school-poverty bands, including attendance-adjusted fits. |
| 7 | `build_oregon_ba_school_poverty_joint_model.py` | Compare BA+-only, poverty-only, and joint fits on the same schools. |
| 8 | `build_evidence_lab_two_factor_assets.py` | Draw the added-R-squared chart from #7's CSV; no model is refitted here. |
| 9 | `build_oregon_ba_school_poverty_residuals.py` | Ask whether differences above/below a BA+-only fitted line track school poverty. |
| 10 | `build_ho_proficiency_thresholds.py` | Show information hidden by one proficiency threshold and sensitivity to alternative scores assigned to performance levels. |
| 11 | `report_spending_classsize_effects.py` | Explore spending/class-size associations with simple, adjusted, and within-district fits. |
| 12 | `report_spending_classsize_ridge.py` | Use ridge regression and school-grouped validation to examine correlated predictors. |
| 13 | `income_education_model_common.py` | Shared input checks, school selection, fitting, and repeated validation for #1–4. Import this module; do not run it as a report. |
| 14 | `analysis_utils.py` | Small weighted-statistics and regression helpers; no file I/O or standalone report. |
| 15 | `assessment_performance_metrics.py` | Derive a scored denominator from complete performance-level counts; no standalone report. |

## Running the downloadable copies

Work in a separate local copy: running a generator replaces its named output
files. Keep this layout, with the published site's root as the working directory:

```text
data/processed/                         subject data and optional chunk manifest
evidence-lab/artifacts/scripts/         all Python files, README, requirements
evidence-lab/artifacts/reports/         published inputs/results and regenerated reports
```

The current subjects are 2024–25 ELA, Math, and Science. The three canonical CSV
names are `SchoolDataWithAddressesAndCensusSES.csv`,
`SchoolDataMathWithAddressesAndCensusSES.csv`, and
`SchoolDataScienceWithAddressesAndCensusSES.csv`.

Scripts #1–6 can also read the approved `dashboard_data_manifest.json` and its
chunks when a full subject CSV is absent. Other data-reading entry points need
the full canonical CSVs; a directory containing only the hosting chunks is not
sufficient. Use the corresponding full processed inputs, or reconstruct them
from manifest-ordered chunks (one header only) and verify their source SHA-256
before running. Do not bypass a hash error just to make a different release run.

Install the declared Python packages first:

```sh
python3 -m pip install -r evidence-lab/artifacts/scripts/requirements.txt
```

Then run a report script, for example:

```sh
python3 evidence-lab/artifacts/scripts/report_income_poverty_reassessment.py
```

Scripts #1–7, #9, and #12 have `--help` options. The figure renderer (#8),
threshold study (#10), and spending OLS study (#11) use constants rather than a
command-line parser. Most public copies write under `artifacts/reports/`;
**#10 instead writes beside its script**, as specified by its `OUT_DIR`.
The source-tree versions can have different output roots; these instructions
describe the downloadable copies.

For the two-factor chart, run #7 before #8 if the CSV needs rebuilding. The
residual study (#9) imports #7's functions but reads the original subject data,
not #7's output CSV. Likewise #6 imports #5 without needing #5's report first.
These generators produce numerical companions and selected figures; they do
not recreate every surrounding website HTML page.

## Reading the calculations

- **Observation:** the modeling entry points #1–7 and #9 use one official All
  Grades outcome per eligible school; observed grade rows first classify
  whole-school eligibility. Elementary-only is primary, with other scopes
  explicitly labeled as sensitivities. #8 plots #7's results. #10 uses a broader
  All Grades school sample. #11–12 use school-grade rows. Do not assume sample
  sizes or results from these families are directly interchangeable.
- **Weights and units:** achievement uses scored students, not participants.
  Attendance has its own included-student denominator. BA+ refers to adults in
  the school-site census tract; enrolled-student poverty is a different measure.
  Headers specify whether a quantity is a fraction, percent, dollars, or a
  standardized coefficient.
- **Fit versus prediction:** in-sample R-squared describes a fitted sample.
  Cross-validation predicts held-out rows; school-row splits are not the same
  as district-held-out validation. Repeated-split ranges describe stability,
  not confidence intervals. The ridge report's penalty-selection scores are
  not an independent final test.
- **Missing and censored values:** a suppressed value is not zero. Some poverty
  reports compare documented interval midpoints, endpoints, and exact-only
  samples. The code comments identify these choices and whether model samples
  differ. These are descriptive associations, not intervention-effect estimates.

The separate browser controller `simulation.js`, loaded by Simulation Lab, fits
a broader school-grade interaction model in the browser. It is not an entry
point to this Python package; its comments explain the scenario units,
model-based uncertainty bands, and differences from the report samples.
