File size: 2,719 Bytes
645c144
 
 
 
 
53e7528
645c144
 
 
 
 
 
 
 
53e7528
 
 
 
 
645c144
 
53e7528
 
 
 
645c144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f96a71c
 
 
 
 
 
 
 
645c144
 
 
 
 
 
53e7528
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import gradio as gr
import numpy as np
import polars as pl
import pydicom
from PIL import Image
from pydicom.errors import InvalidDicomError


def read_and_preprocess_dicom(file_path: str):
    """
    Function to read and preprocess DICOM files
    :param file_path: Path to the DICOM file
    :return: Image data (in PIL format) and metadata (in pandas DataFrame format)
    """
    try:
        # Read the DICOM file
        dicom_data = pydicom.dcmread(file_path)
    except InvalidDicomError:
        raise gr.Error("The uploaded file is not a valid DICOM file.")

    # Get the pixel data
    try:
        pixel_array = dicom_data.pixel_array
    except AttributeError:
        raise gr.Error("The uploaded DICOM file has no pixel data.")

    # Normalize the pixel data to 8-bit and convert to a PIL image
    if pixel_array.dtype != np.uint8:
        pixel_array = ((pixel_array - np.min(pixel_array)) / (np.max(pixel_array) - np.min(pixel_array)) * 255).astype(
            np.uint8)
    image = Image.fromarray(pixel_array)

    # Collect metadata in dictionary format and convert to DataFrame
    metadata_dict = {elem.name: str(elem.value) for elem in dicom_data.iterall() if elem.name != 'Pixel Data'}
    df_metadata = pl.DataFrame({
        "Key": list(metadata_dict.keys()),
        "Value": list(metadata_dict.values())
    })

    return image, df_metadata.to_pandas()  # Convert to pandas DataFrame for Gradio compatibility


def build_interface():
    """
    Function to build the Gradio interface
    """
    theme = gr.themes.Soft(
        primary_hue=gr.themes.colors.emerald,
        secondary_hue=gr.themes.colors.emerald
    )

    with gr.Blocks(title='DICOM Viewer', theme=theme) as demo:
        gr.Markdown(
            """
            # DICOM Viewer
            This app reads a DICOM file and displays the image and metadata.
            """
        )
        with gr.Column():
            file_path = gr.File(label="Input DICOM Data")

            with gr.Row():
                dicom_image = gr.Image(type="pil", label="DICOM Image")
                dicom_meta = gr.Dataframe(headers=None, label="Metadata")

            inputs = [file_path]
            outputs = [dicom_image, dicom_meta]
            file_path.upload(fn=read_and_preprocess_dicom, inputs=inputs, outputs=outputs)

            clear_button = gr.ClearButton(components=inputs + outputs, )

            example = gr.Examples(
                ['assets/sample.dcm'],
                inputs=inputs,
                outputs=outputs,
                fn=read_and_preprocess_dicom,
                cache_examples=True
            )

    return demo


if __name__ == '__main__':
    demo = build_interface()
    demo.launch()