v1 · API Docs

# Python Integration Guide

This page provides a complete, ready-to-use Python script for integrating the LeapAI CXR API into your application. The script demonstrates health checks, single inference, and bulk inference.


# Prerequisites

Install the required Python package:

pip install requests

# Configuration

Update the following constants in the script with your environment details:

BASE_URL = "http://<server-ip>:8500"
TOKEN = "your_jwt_token"

# Complete Integration Script

"""
LeapAI CXR - Python Integration Script
======================================
A reference implementation for interacting with the
LeapAI CXR inference API.

Usage:
    python leapai_cxr_client.py

Requirements:
    pip install requests
"""

import os
import json
import requests
from typing import Optional


# =============================================================================
# Configuration
# =============================================================================

BASE_URL = "http://localhost:8500"  # LeapAI CXR server URL
TOKEN = "your_jwt_token"            # JWT token provided post-installation


# =============================================================================
# Health Check
# =============================================================================

def health_check(base_url: str) -> bool:
    """
    Check if the LeapAI CXR server is running and responsive.
    """
    try:
        response = requests.get(f"{base_url}/ping")
        if response.status_code == 200:
            data = response.json()
            print(f"[OK] Server is healthy: {data}")
            return True
        print(f"[ERR] Server returned status {response.status_code}")
        return False
    except requests.exceptions.ConnectionError:
        print(f"[ERR] Server is not reachable at {base_url}")
        return False


# =============================================================================
# Single Inference
# =============================================================================

def run_single_inference(
    base_url: str,
    token: str,
    input_image_path: str,
    save_to_disk: bool,
    patient_id: Optional[str] = None,
    output_folder_path: Optional[str] = None,
    timeout: int = 300,
) -> dict:
    """
    Run AI inference on a single DICOM image.

    If save_to_disk is True, output files are written under output_folder_path.
    If save_to_disk is False, source_image and heatmap are base64-encoded PNG strings
    in the response.
    """
    url = f"{base_url}/single_inference"
    payload = {
        "input_image_path": input_image_path,
        "save_to_disk": save_to_disk,
    }
    if patient_id:
        payload["patient_id"] = patient_id
    if save_to_disk:
        payload["output_folder_path"] = output_folder_path

    headers = {
        "Content-Type": "application/json",
        "Authorization": token,  # NOTE: No "Bearer" prefix
    }

     try:
        response = requests.post(url, json=payload, headers=headers, timeout=timeout)
        response_data = response.json()

        if response.status_code == 200 and response_data.get("Result") == "Success":
            print(f"[✓] Single inference completed successfully.")
        else:
            print(f"[✗] Single inference failed: {response_data.get('Message')}")

        return response_data

    except requests.exceptions.Timeout:
        print("[✗] Request timed out. The image may be too large.")
        return {"Result": "Failure", "Message": "Request timeout"}
    except Exception as e:
        print(f"[✗] Single inference error: {e}")
        return {"Result": "Failure", "Message": str(e)}


# =============================================================================
# Bulk Inference
# =============================================================================

def run_bulk_inference(
    base_url: str,
    token: str,
    input_folder_path: str,
    output_folder_path: str,
    timeout: int = 3600,
) -> dict:
    """
    Run AI inference on all DICOM images in a folder.
    """
    url = f"{base_url}/bulk_inference"
    payload = {
        "input_folder_path": input_folder_path,
        "output_folder_path": output_folder_path,
    }
    headers = {
        "Content-Type": "application/json",
        "Authorization": token,  # NOTE: No "Bearer" prefix
    }

    try:
        print(f"[…] Starting bulk inference on: {input_folder_path}")
        print(f"    Output will be saved to:    {output_folder_path}")
        print(f"    Timeout: {timeout}s. This may take a while...")

        response = requests.post(url, json=payload, headers=headers, timeout=timeout)
        response_data = response.json()

        if response.status_code == 200 and response_data.get("Result") == "Success":
            print(f"[✓] Bulk inference completed successfully.")
        else:
            print(f"[✗] Bulk inference failed: {response_data.get('Message')}")

        return response_data

    except requests.exceptions.Timeout:
        print("[✗] Request timed out. Consider increasing the timeout for large batches.")
        return {"Result": "Failure", "Message": "Request timeout"}
    except Exception as e:
        print(f"[✗] Bulk inference error: {e}")
        return {"Result": "Failure", "Message": str(e)}


# =============================================================================
# Read Prediction Results
# =============================================================================

def read_prediction_json(json_path: str) -> Optional[dict]:
    """
    Read and parse a prediction JSON file generated by the inference engine.
    """
    try:
        with open(json_path, "r") as f:
            data = json.load(f)

        print("\n" + "=" * 60)
        print(f"Prediction Results: {os.path.basename(json_path)}")
        print("=" * 60)
        print(f"Overall Result : {data.get('result', 'N/A')}")
        print(f"Patient ID     : {data.get('metadata', {}).get('patient_id', 'N/A')}")
        print(f"Patient Name   : {data.get('metadata', {}).get('patient_name', 'N/A')}")
        print("=" * 60)
        print(f"{'Condition':<25} {'Detected':<10} {'Confidence':<12}")
        print("-" * 47)

        for finding in data.get("findings", []):
            name = finding.get("name", "Unknown")
            presence = "YES" if finding.get("presence") else "NO"
            confidence = finding.get("confidence", 0.0)
            print(f"{name:<25} {presence:<10} {confidence:.4f}")

        print("=" * 60)
        print(f"Heatmap      : {data.get('heatmap', 'N/A')}")
        print(f"Source Image : {data.get('source_image', 'N/A')}")
        print("=" * 60 + "\n")

        return data

    except FileNotFoundError:
        print(f"[ERR] File not found: {json_path}")
        return None
    except json.JSONDecodeError:
        print(f"[ERR] Invalid JSON: {json_path}")
        return None


# =============================================================================
# Main - Example Usage
# =============================================================================

def main():
    """
    Example workflow demonstrating the full LeapAI CXR integration:
      1. Health check
      2. Run single inference
      3. Run bulk inference (optional)
      4. Parse prediction results
    """

    print("\n" + "=" * 60)
    print("LeapAI CXR - Python Integration Example")
    print("=" * 60 + "\n")

    # Step 1: Health Check
    print("[Step 1] Checking server health...")
    if not health_check(BASE_URL):
        print("Server is not available. Exiting.")
        return

    # Step 2: Single Inference
    print("\n[Step 2] Running single inference...")
    single_result = run_single_inference(
        base_url=BASE_URL,
        token=TOKEN,
        input_image_path="C:/data/patient001.dcm",
        save_to_disk=True,
        patient_id="PAT001",
        output_folder_path="C:/output/",
    )
    print(json.dumps(single_result, indent=2))

    # Step 3: Bulk Inference (Optional)
    print("\n[Step 3] Running bulk inference...")
    bulk_result = run_bulk_inference(
        base_url=BASE_URL,
        token=TOKEN,
        input_folder_path="C:/data/dicom/batch_001/",
        output_folder_path="C:/output/batch_001/",
        timeout=3600,
    )
    print(json.dumps(bulk_result, indent=2))

    # Step 4: Read Prediction Results
    print("\n[Step 4] Reading prediction results...")
    prediction_file = "C:/output/<patient_id>/<patient_id>_predictions.json"
    read_prediction_json(prediction_file)


if __name__ == "__main__":
    main()

# Function Reference

Function Description
health_check(...) Verify the server is running via /ping
run_single_inference(...) Process a single DICOM image
run_bulk_inference(...) Process a folder of DICOM images
read_prediction_json(...) Parse and display a _predictions.json file

# Key Notes