Breast ultrasound benign-malignant diagnosis with segmentation-assisted multi-task learning.
Project description
JwzTumor
Breast ultrasound benign-malignant diagnosis with segmentation-assisted multi-task learning.
Overview
JwzTumor implements LABDG-Pre + DGBC-MTLNet + MPTC-Head, a multi-task system for breast tumor diagnosis from ultrasound images:
- LABDG-Pre: Lesion-aware boundary-preserving domain-generalized preprocessing
- DGBC-MTLNet: Domain-generalized boundary-context collaborative multi-task network (CNN-Mamba hybrid)
- MPTC-Head: Morphology-prompted topology-consistent classification head (4-stream)
The system outputs: classification probability, segmentation mask, edge map, SDM, uncertainty map, and explainability visualizations.
Project Structure
jwz-tumor/
pyproject.toml
configs/ # 8 YAML configs
dataset/ # BUSBRA + BUSI data
web/ # React + Vite + TypeScript frontend source
scripts/ # Frontend packaging and maintenance scripts
src/JwzTumor/
cli/ # CLI entrypoints, including jwzt server
data/ # Datasets, preprocessing, augmentation, cache, audit, collate
models/ # LABDG-Pre, DGBCEncoder, MPP, decoder, MPTC-Head
losses/ # 7 loss modules + factory
training/ # Stage trainer, scheduler, callbacks
inference/ # Predictor, TTA, postprocessing, visualization
evaluation/ # Classification + segmentation metrics
server/ # FastAPI inference server, /api/report, packaged static UI
report/ # Rule/LLM/hybrid report generation
ui/ # Built frontend files served by jwzt server --with-ui
utils/ # Config, seed, logging, I/O, registry
tests/ # Python tests
Datasets
BUSBRA (Training)
- Images:
bus_{id}-{side}.png, Masks:mask_{id}-{side}.png - Labels:
bus_data.csv(Pathology: benign/malignant) - CV:
5-fold-cv.csvor10-fold-cv.csv - Case-level splitting (no leak)
BUSI (Testing)
- Directory-based:
benign/,malignant/ - Skip:
normal-不使用/ - Multi-mask: OR union in original size before resize
- RGB images converted to grayscale
Installation
# Install from PyPI
pip install JwzTumor
# Using uv
uv pip install -e .
# Development
uv pip install -e ".[dev]"
Quick Start
# Show version
jwzt version
# Export config template
jwzt get --name train_full --output configs/my_config.yaml
# Train
jwzt train --config configs/train_full.yaml --experiment-name exp001 --fold 1
# Stage-specific training
jwzt train --config configs/train_pretrain_pre.yaml --stage pretrain_pre --fold 1
jwzt train --config configs/train_pretrain_seg.yaml --stage pretrain_seg --fold 1
jwzt train --config configs/train_cls_head.yaml --stage train_cls --fold 1
jwzt train --config configs/train_finetune.yaml --stage finetune_all --fold 1
# Predict
jwzt pred --config configs/infer_busi.yaml --model checkpoints/best_auc.ckpt --data dataset/Dataset_BUSI_with_GT --output outputs/busi_predictions
# Evaluate
jwzt eval --config configs/eval_busi.yaml --pred outputs/busi_predictions --data dataset/Dataset_BUSI_with_GT
# Audit dataset
jwzt audit-data --data-root dataset --output outputs/dataset_audit_summary.json
# Debug training
jwzt train --config configs/train_debug.yaml --experiment-name debug_run
Clinical Workbench UI
The project now includes a clinical auxiliary diagnosis workbench for breast ultrasound cases:
- frontend source lives in
web/ - packaged static UI lives in
src/JwzTumor/server/ui/ - backend report generation lives in
src/JwzTumor/server/report/ - report API endpoint is
POST /api/report
The frontend supports:
- single-image and dual-image diagnosis modes
- patient metadata and structured ultrasound field entry
- asynchronous inference progress
- editable structured report rendering
- browser-local draft/history persistence
- JSON export and PDF export
Frontend Development
Install frontend dependencies:
cd web
npm install
Configure the API target with either .env or shell environment variables:
cp .env.example .env
.env example:
VITE_JWZT_API_BASE_URL=http://127.0.0.1:8000
Terminal temporary variable example:
cd web
VITE_JWZT_API_BASE_URL=https://your-api.example.com npm run dev -- --host 0.0.0.0 --port 5173
Start the standalone frontend dev server:
cd web
npm run dev -- --host 0.0.0.0 --port 5173
The frontend resolves the backend address in this order:
- runtime
config.jsinjected by the hosting server VITE_JWZT_API_BASE_URL- fallback
http://127.0.0.1:8000
Inference Server
Install server dependencies:
pip install -e ".[server]"
Start the inference API:
jwzt server \
--model checkpoints/best_auc.ckpt \
--config configs/infer_busi.yaml \
--host 0.0.0.0 \
--port 8000
The same values can also be stored in a server YAML file. Generate an annotated example with:
jwzt get -t server -o configs/server.yaml
Then start from that file:
jwzt server --config configs/server.yaml
Precedence is CLI options and their environment variables first, then YAML server: / report_llm: sections, then built-in defaults.
Useful CLI environment variables are also supported, so system variables and one-shot terminal variables work without editing code:
export JWZT_MODEL=checkpoints/best_auc.ckpt
export JWZT_CONFIG=configs/infer_busi.yaml
export JWZT_HOST=0.0.0.0
export JWZT_PORT=8000
Or:
JWZT_MODEL=checkpoints/best_auc.ckpt JWZT_PORT=8000 jwzt server
Server-related environment variables map directly to CLI options and YAML keys:
JWZT_MODEL -> server.model / --model
JWZT_HOST -> server.host / --host
JWZT_PORT -> server.port / --port
JWZT_DEVICE -> server.device / --device
JWZT_TTA -> server.tta / --tta or --no-tta
JWZT_MAX_QUEUE -> server.max_queue / --max-queue
JWZT_MAX_UPLOAD_MB -> server.max_upload_mb / --max-upload-mb
JWZT_MAX_BATCH_SIZE -> server.max_batch_size / --max-batch-size
JWZT_CORS_ORIGINS -> server.cors_origins / --cors-origins
JWZT_LOG_DIR -> server.log_dir / --log-dir
JWZT_WITH_UI -> server.with_ui / --with-ui or --no-with-ui
JWZT_UI_DIR -> server.ui_dir / --ui-dir
JWZT_UI_HOST -> server.ui_host / --ui-host
JWZT_UI_PORT -> server.ui_port / --ui-port
JWZT_UI_API_BASE_URL -> server.ui_api_base_url / --ui-api-base-url
JWZT_NO_UI -> server.no_ui / --no-ui
UI Hosting Modes
Same-Port Hosting
Serve the packaged UI from the same FastAPI service and port:
jwzt server \
--model checkpoints/best_auc.ckpt \
--config configs/infer_busi.yaml \
--with-ui \
--host 0.0.0.0 \
--port 8000
This serves:
- API:
http://127.0.0.1:8000/api/... - UI:
http://127.0.0.1:8000/
Separate UI Port
Serve the API and UI on different ports:
jwzt server \
--model checkpoints/best_auc.ckpt \
--config configs/infer_busi.yaml \
--with-ui \
--host 0.0.0.0 \
--port 8000 \
--ui-host 0.0.0.0 \
--ui-port 8080 \
--ui-api-base-url http://127.0.0.1:8000
Equivalent environment variables:
export JWZT_UI_HOST=0.0.0.0
export JWZT_UI_PORT=8080
export JWZT_UI_API_BASE_URL=http://127.0.0.1:8000
If you already have an external built frontend directory, you can override the packaged UI:
jwzt server \
--model checkpoints/best_auc.ckpt \
--config configs/infer_busi.yaml \
--with-ui \
--ui-dir /absolute/path/to/web/dist
Runtime config.js
When the UI is served by jwzt server, the backend injects a runtime config.js file at /config.js:
window.__JWZT_CONFIG__ = { apiBaseUrl: "http://127.0.0.1:8000" };
This lets the same built frontend work in:
- local standalone development
- same-port packaged serving
- separate-port packaged serving
- reverse-proxy or public-domain deployments
Report API
Clinical report generation is exposed by:
POST /api/report
Supported report_mode values:
rule: deterministic local rule templatellm: editable sections generated by the configured LLMhybrid: rule template with LLM refinement and rule fallback on failure
The frontend uses /api/report first and falls back to a local rule composer if report generation fails.
OpenAI-Compatible LLM Configuration
/api/report can use any OpenAI-Compatible chat completions provider. Configure it with environment variables:
export JWZT_REPORT_LLM_BASE_URL=https://your-openai-compatible.example.com/v1
export JWZT_REPORT_LLM_API_KEY=sk-...
export JWZT_REPORT_LLM_MODEL=gpt-4.1-mini
Optional tuning variables:
export JWZT_REPORT_LLM_TIMEOUT=60
export JWZT_REPORT_LLM_MAX_RETRIES=2
export JWZT_REPORT_LLM_TEMPERATURE=0.2
The same provider settings can be placed in the server YAML:
report_llm:
base_url: https://your-openai-compatible.example.com/v1
api_key: sk-...
model: gpt-4.1-mini
timeout: 60
max_retries: 2
temperature: 0.2
Equivalent CLI flags are available:
jwzt server \
--config configs/server.yaml \
--report-llm-base-url https://your-openai-compatible.example.com/v1 \
--report-llm-api-key sk-... \
--report-llm-model gpt-4.1-mini
If these variables are absent, the report service stays in rule-only fallback mode for editable sections.
Rebuild Packaged UI
After changing the frontend, rebuild and copy the static bundle into the Python package:
./scripts/build_web_ui.sh
Training Strategy
Four-stage training:
- pretrain_pre: Train LABDG-Pre only (coarse localization, structure maps)
- pretrain_seg: Train DGBC-MTLNet segmentation (encoder + decoder)
- train_cls: Train MPTC-Head only (freeze encoder + preprocessing)
- finetune_all: End-to-end fine-tuning with all losses
Metrics
Classification: AUC, Accuracy, Sensitivity, Specificity, Precision, F1 Segmentation: Dice, IoU, HD95, Boundary-F1
Stargazers over time
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jwztumor-1.0.11.tar.gz.
File metadata
- Download URL: jwztumor-1.0.11.tar.gz
- Upload date:
- Size: 445.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bfae73254859216f7e8e4d96536bcd4799f3595f91cbc340b468f941a3980256
|
|
| MD5 |
47646a1bbe60951df0f039dc4f2c6d3e
|
|
| BLAKE2b-256 |
fe75c6a625d9facf03d4e819048f4697d4da4fe6947a7de99a290527d7f6f450
|
File details
Details for the file jwztumor-1.0.11-py3-none-any.whl.
File metadata
- Download URL: jwztumor-1.0.11-py3-none-any.whl
- Upload date:
- Size: 460.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a2141ec29a7fb2e11dca2819662803de1494acf60d69ca584502e5b79bd6af3
|
|
| MD5 |
8a6a0d63513e2d438942b9ef3c03774a
|
|
| BLAKE2b-256 |
e391e33b60905d2bfcc2dff7f8260460b99244efdea199a16de84380b1e1b038
|