Title: IDP Ensemble Scoring with Given Open-Source Tools
Domain: life_sciences — Biomolecular Structure & Design

Summary: Rank 5 IDP ensemble generation models by how well their ensembles match experimental NMR data (chemical shifts, J-couplings, NOE/PRE) using UCBShift and X-EISD.

Task prompt:
You are a computational structural biologist. Your task is to rank 5 IDP (intrinsically disordered protein) ensemble generation models by how well their ensembles match experimental NMR data.

## Your Task

Use the tools provided locally to back-calculate experimental observables from protein ensemble conformers, score each ensemble against experimental data, then normalize and rank the models.

### Step 1: Set up your environment
Install the required Python dependencies for CSpred/UCBShift and xeisd. The tools are provided under `/input`. Key dependencies include numpy, pandas, biopython==1.74, scikit-learn==0.22, joblib, matplotlib.

### Step 2: Back-calculate observables
For each (model, protein, conformer):
- Chemical Shifts (CS): use UCBShift via `/input/CSpred/CSpred.py`
- J-couplings (JC), NOE, PRE: use `/input/xeisd/calculator.py`

### Step 3: Score ensembles
Score each (model, protein) ensemble on the full 200-conformer pool using `xeisd.optimizer.XEISD.calc_scores()`. This produces one row per (model, protein) with columns: cs_score, jc_score, noe_score, pre_score.

### Step 4: Normalize and rank
- For each observable, build a method x protein matrix of raw scores restricted to the test protein set for that observable (defined in `/input/info.py`). Min-max normalize each protein column across methods: (X - Xmin) / (Xmax - Xmin). Row-mean across proteins gives one number per (method, observable).
- For each (method, protein), sum the available per-observable raw scores into raw_total[method, protein]. Min-max normalize each protein column of raw_total across methods. Row-mean gives the Total score. Rank by Total descending (higher = better experimental agreement, on [0, 1]).

### Step 5: Save output
Save the final results as a CSV file to:
`/output/Final_Output.csv`

The CSV must have these exact columns: Method, Total, CS, JC, NOE/PRE
Each row is one model (Model1 through Model5).
All numeric values must be between 0 and 1.

## Input Data
- `/input/Ensembles/` -- 5 models (Model1-5), each with protein subdirectories containing 200 conformer PDB files
- `/input/Experimental_Data/` -- experimental NMR data per protein
- `/input/CSpred/` -- UCBShift tool with models and binaries
- `/input/xeisd/` -- X-EISD scoring module
- `/input/info.py` -- defines test protein sets per observable

## Output
Save your final CSV to: `/output/Final_Output.csv`

## Constraints
- Do NOT use web search. Use only the tools provided locally.
- Use only CS, JC, and NOE/PRE observables. Do NOT use Rg, FRET, SAXS, or any other observable type.
- Creating subprocesses and helper scripts is permitted.


The agent must:
Set up a Python environment with correct dependencies (biopython==1.74, scikit-learn==0.22)
Back-calculate CS via UCBShift and JC/NOE/PRE via xeisd calculator
Score ensembles using xeisd.optimizer.XEISD.calc_scores()
Min-max normalize per observable and compute total ranking
Save Final_Output.csv to the output directory

Software: UCBShift (CSpred)
X-EISD (xeisd)

Input files:
name: CSpred
format: directory
path: input/CSpred/
description: UCBShift chemical shift predictor with models and binaries
name: xeisd
format: directory
path: input/xeisd/
description: X-EISD ensemble scoring module
name: Ensembles
format: directory
path: input/Ensembles/
description: 5 models x ~36 proteins x 200 PDB conformers
name: Experimental_Data
format: directory
path: input/Experimental_Data/
description: Per-protein experimental NMR data
name: info.py
format: python
path: input/info.py
description: Test protein sets per observable