Metadata-Version: 2.4
Name: clinically-structured-metric
Version: 0.1.0
Summary: Clinically Structured Metric (CSM) for structured evaluation of CCTA reports
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: pandas>=1.5
Requires-Dist: openpyxl>=3.0

# Clinically Structured Metric (CSM)

CSM is a clinically weighted metric for evaluating generated coronary CT angiography (CCTA) reports. It accepts Chinese and English report text, identifies findings at the patient, vessel, and segment anatomical levels, and combines the applicable agreement components at the coarser anatomical level of each report pair.

This directory is self-contained and can be published as an independent repository. The evaluator does not depend on experiment workbooks or files elsewhere in the parent research project.

## Installation

Install CSM from PyPI:

```bash
pip install clinically-structured-metric
```

Import the installed package as:

```python
import CSM
```

For local development, install the repository in editable mode from the
repository root:

```bash
pip install -e .
```

Python 3.9 or newer is required.

## Command line

The input table must contain a ground-truth report column and a prediction report column. Every non-empty cell must contain Chinese or English report text.

```bash
CSM examples/input.csv --gt-col gt --pred-col pred --output results/CSM.xlsx
```

The same interface is available without the installed console command:

```bash
python3 -m CSM examples/input.csv --gt-col gt --pred-col pred
```

## Output

The evaluator preserves all input columns and appends:

| Column | Meaning |
| --- | --- |
| `gt_anatomical_level` | Anatomical level identified in the reference report |
| `pred_anatomical_level` | Anatomical level identified in the generated report |
| `csm_anatomical_level` | Coarser anatomical level used for weighting |
| `CSM` | Clinically weighted score normalized to the range 0–1 |
| `d_p` | Patient-level coronary dominance agreement |
| `c_p` | Patient-level calcification agreement |
| `n_p` | Patient-level narrowing agreement |
| `n_v` | Vessel-level narrowing agreement |
| `p_v` | Vessel-level plaque agreement |
| `q_s` | Segment-level finding agreement |

If a component is not applicable, it is excluded and the remaining weights are proportionally rescaled. If either report is irrelevant or cannot be parsed, CSM is zero.

## Examples

### Paired reports

Input:

```python
from CSM import evaluate_pair

ground_truth = (
    "Right coronary dominant type\n"
    "1. No significant coronary artery calcification.\n"
    "2. LM: No significant stenosis.\n"
    "Left anterior descending artery: No significant stenosis.\n"
    "Left circumflex artery: No significant stenosis.\n"
    "Right coronary artery: No significant stenosis."
)
prediction = (
    "Right coronary dominant type\n"
    "1. No significant coronary artery calcification.\n"
    "2. Left main coronary artery: No significant stenosis.\n"
    "Left anterior descending artery: root: mixed plaque with lumen "
    "mild-severe stenosis.\n"
    "Circumflex artery: proximal segment: mixed plaque with lumen mild stenosis.\n"
    "RCA: proximal segment: mixed plaque with lumen mild-moderate stenosis."
)

result = evaluate_pair(ground_truth, prediction)
print(result)
```

Output:

```python
{
    "gt_anatomical_level": "vessel",
    "pred_anatomical_level": "segment",
    "csm_anatomical_level": "vessel",
    "CSM": 0.6221661493964521,
    "d_p": 1.0,
    "c_p": 1.0,
    "n_p": 0.0,
    "n_v": 0.2,
    "p_v": None,
    "q_s": 0.0,
}
```

### Single report

Input:

```python
from CSM import analyze_report

report = (
    "右冠优势型\n"
    "1.冠状动脉未见明确钙化。\n"
    "2.左主干未见明确狭窄；\n"
    "前降支未见明确狭窄；\n"
    "回旋支未见明确狭窄；\n"
    "右冠状动脉未见明确狭窄。"
)

result = analyze_report(report)
print(result)
```

Output:

```python
{"anatomical_level": "vessel"}
```
