bone_2026/run.sh

191 lines
9.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
#
# DXA Quality Assessment — единая точка входа.
#
# Использование: ./run.sh <команда> [аргументы]
# ./run.sh train [доп. аргументы для src.dxa.train]
# ./run.sh infer <вход> <выход.xlsx|.csv> [доп. аргументы]
# ./run.sh serve [порт] http://localhost:PORT — анализ; /label — ручная разметка
# ./run.sh label
# ./run.sh split
# ./run.sh review [--limit N] пакет ручной разметки для врача; --merge — наложить вердикты
# ./run.sh rename [--apply]
# ./run.sh compare
# ./run.sh test
#
# Скрипт намеренно не содержит своей реализации обучения и инференса: вся
# логика живёт в Python-модулях, а здесь только вызовы. Дублирование цикла
# обучения (как было раньше) приводило к расхождению правил между режимами.
set -euo pipefail
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
PYTHON=${PYTHON:-python3}
DATA_ROOT=${DATA_ROOT:-dataset_hack}
ANNOTATION_PATH=${ANNOTATION_PATH:-"dataset_hack/НД_для_обучения/разметка.xlsx"}
MODEL_PATH=${MODEL_PATH:-models/dxa_model.pth}
LABELS_DIR=${LABELS_DIR:-labels}
LABELS_CSV=${LABELS_CSV:-labels/labels_images.csv}
LABELS_REFERENCE_CSV=${LABELS_REFERENCE_CSV:-labels/labels_images_expert.csv}
SPLIT_FILE=${SPLIT_FILE:-labels/split_expert_seed42.json}
RENAME_MAP=${RENAME_MAP:-labels/rename_map.csv}
REVIEW_OUT=${REVIEW_OUT:-review/doctor_review.html}
PORT=${PORT:-8000}
command=${1:-help}
shift || true
case "$command" in
train)
echo -e "${YELLOW}Обучение классификатора качества DXA${NC}"
echo " метки: $LABELS_CSV"
"$PYTHON" -m src.dxa.train \
--data-root "$DATA_ROOT" \
--annotation-path "$ANNOTATION_PATH" \
--labels-csv "$LABELS_CSV" \
--output-dir "$(dirname "$MODEL_PATH")" \
"$@"
echo -e "${GREEN}Готово. Чекпоинт: ${MODEL_PATH}${NC}"
;;
infer)
input_path=${1:-dataset_hack/Для теста}
output_path=${2:-results.xlsx}
shift 2 2>/dev/null || true
echo -e "${YELLOW}Пакетная обработка${NC}"
echo " вход: $input_path"
echo " выход: $output_path"
"$PYTHON" -m src.dxa.inference \
--input-path "$input_path" \
--output-path "$output_path" \
--model-path "$MODEL_PATH" \
"$@"
echo -e "${GREEN}Готово: ${output_path}${NC}"
;;
serve)
echo -e "${YELLOW}Запуск API на порту ${PORT}${NC}"
DXA_MODEL_PATH="$MODEL_PATH" \
"$PYTHON" -m uvicorn src.main:app --host 0.0.0.0 --port "$PORT"
;;
label)
echo -e "${YELLOW}Разметка датасета на уровне снимков${NC}"
echo " таблица: $ANNOTATION_PATH"
"$PYTHON" -m src.dxa.excel_labels \
--data-root "$DATA_ROOT" \
--excel "$ANNOTATION_PATH" \
--out-dir "$LABELS_DIR" \
"$@"
;;
split)
echo -e "${YELLOW}Фиксация разбиения для сравнения правил разметки${NC}"
echo " стратификация по эталону: $LABELS_REFERENCE_CSV"
"$PYTHON" -m src.dxa.train \
--data-root "$DATA_ROOT" \
--annotation-path "$ANNOTATION_PATH" \
--labels-csv "$LABELS_REFERENCE_CSV" \
--export-split "$SPLIT_FILE" \
"$@"
;;
review)
# Два режима у одной команды: собрать пакет для специалиста или наложить
# вернувшиеся вердикты. Наличие --merge в аргументах и различает их.
if [[ " $* " == *" --merge "* ]]; then
echo -e "${YELLOW}Наложение вердиктов специалиста на построенную разметку${NC}"
"$PYTHON" -m src.dxa.review_pack \
--data-root "$DATA_ROOT" \
--annotation-path "$ANNOTATION_PATH" \
--labels-csv "$LABELS_CSV" \
"$@"
else
echo -e "${YELLOW}Пакет ручной разметки для специалиста${NC}"
echo " пакет: $REVIEW_OUT (переопределяется --out)"
echo " вернувшиеся вердикты: ./run.sh review --merge review/doctor.csv --out labels/labels_images_reviewed.csv"
"$PYTHON" -m src.dxa.review_pack \
--data-root "$DATA_ROOT" \
--annotation-path "$ANNOTATION_PATH" \
--labels-csv "$LABELS_CSV" \
--out "$REVIEW_OUT" \
"$@"
fi
;;
rename)
echo -e "${YELLOW}Приведение имён DICOM к единому виду${NC}"
if [ "${1:-}" = "--apply" ]; then
echo -e "${RED}Правка имён. Карта отката: $RENAME_MAP${NC}"
else
echo " режим плана; для правки добавьте --apply"
fi
"$PYTHON" -m src.dxa.rename_files \
--data-root "$DATA_ROOT" \
--mapping "$RENAME_MAP" \
"$@"
;;
compare)
echo -e "${YELLOW}Сравнение источников разметки на одном held-out наборе${NC}"
echo " разбиение: $SPLIT_FILE"
if [ ! -f "$SPLIT_FILE" ]; then
echo -e "${RED}Нет файла разбиения. Сначала: ./run.sh split${NC}" >&2
exit 1
fi
"$PYTHON" -m src.dxa.compare_labels \
--data-root "$DATA_ROOT" \
--annotation-path "$ANNOTATION_PATH" \
--split-file "$SPLIT_FILE" \
"$@"
;;
test)
echo -e "${YELLOW}Запуск тестов${NC}"
"$PYTHON" -m pytest tests/ -q
;;
help|*)
cat <<'USAGE'
DXA Quality Assessment — управление запуском
Команды:
train [аргументы] Обучить классификатор качества.
Пример: ./run.sh train --epochs 100 --head mlp
infer <вход> <выход> [арг.] Пакетная обработка DICOM (файл или каталог).
Пример: ./run.sh infer "dataset_hack/Для теста" results.xlsx
Дополнительно: --zip-out masks.zip
serve [порт] Запустить HTTP API и веб-интерфейс.
label [аргументы] Разметить датасет на уровне снимков по Excel.
Результат: labels/labels_images.csv|.xlsx
split [аргументы] Зафиксировать разбиение по исследованиям.
Результат: labels/split_expert_seed42.json
rename [--apply] Привести имена DICOM к виду область_NN[_метка].
Без --apply — только план; карта отката пишется
до правки (labels/rename_map.csv)
compare [аргументы] Сравнить источники разметки на одном held-out
наборе (нужен сначала `./run.sh split`).
test Запустить тесты.
Переменные окружения:
DATA_ROOT Каталог датасета (по умолчанию dataset_hack)
ANNOTATION_PATH Excel с экспертной разметкой исследований
MODEL_PATH Путь к чекпоинту (по умолчанию models/dxa_model.pth)
LABELS_DIR Каталог с результатом разметки (по умолчанию labels)
LABELS_CSV Разметка снимков для обучения (пустая строка — метки из имён файлов)
SPLIT_FILE Файл фиксированного разбиения (labels/split_expert_seed42.json)
LABELS_REFERENCE_CSV Эталон для стратификации разбиения (labels/labels_images_expert.csv)
RENAME_MAP Карта переименований для отката (по умолчанию labels/rename_map.csv)
PORT Порт API (по умолчанию 8000)
PYTHON Интерпретатор (по умолчанию python3)
Типовой порядок работы:
./run.sh label # разметить датасет по Excel
./run.sh train # обучить модель
./run.sh infer dataset_hack results.xlsx
./run.sh serve # веб-интерфейс на http://localhost:8000
./run.sh split && ./run.sh compare # сравнить варианты разметки
USAGE
;;
esac