Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import plotly.express as px | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| import matplotlib as mpl | |
| import numpy as np | |
| from dosemetrics.data import read_byte_data, read_dose, read_masks | |
| from dosemetrics.metrics import dvh_by_structure, dvh_by_dose, dose_summary | |
| from dosemetrics.utils import ( | |
| get_default_constraints, | |
| get_custom_constraints, | |
| compute_mirage_compliance, | |
| ) | |
| def display_summary(doses, structure_mask): | |
| df = dvh_by_structure(doses, structure_mask) | |
| fig = px.line(df, x="Dose", y="Volume", color="Structure") | |
| fig.update_xaxes(showgrid=True) | |
| fig.update_yaxes(showgrid=True) | |
| st.plotly_chart(fig, use_container_width=True) | |
| summary_df = dose_summary(doses, structure_mask) | |
| st.table(summary_df) | |
| return summary_df | |
| def compare_differences(summary_df, selected_structures, ref_id): | |
| diff_table = pd.DataFrame() | |
| st.markdown(f"#### Dose differences between Dose: {id} vs Reference: {ref_id}") | |
| for structure in selected_structures: | |
| diff_table.loc[:, structure] = ( | |
| summary_df[id].loc[structure, :] - summary_df[ref_id].loc[structure, :] | |
| ) | |
| st.table(diff_table) | |
| def display_difference_dvh(doses, structure_mask, selected_structures, ref_id): | |
| for structure in selected_structures: | |
| st.markdown(f"#### DVH comparisons for {structure}") | |
| df = dvh_by_dose(doses, structure_mask[structure], structure) | |
| fig = px.line(df, x="Dose", y="Volume", color="Structure") | |
| fig.update_xaxes(showgrid=True) | |
| fig.update_yaxes(showgrid=True) | |
| st.plotly_chart(fig, use_container_width=True) | |
| def generate_dvh_family( | |
| dose_volume, structure_masks, constraints: pd.DataFrame, structure_of_interest: str | |
| ): | |
| structure_mask = structure_masks[structure_of_interest] | |
| constraint_limit = constraints.loc[structure_of_interest, "Level"] | |
| # Generate DVH for the structure of interest | |
| df = dvh_by_structure(dose_volume, {structure_of_interest: structure_mask}) | |
| # Create a simple plot | |
| fig, ax = plt.subplots() | |
| ax.plot(df["Dose"], df["Volume"]) | |
| ax.set_xlabel("Dose (Gy)") | |
| ax.set_ylabel("Volume (%)") | |
| ax.set_title(f"DVH for {structure_of_interest}") | |
| ax.grid(True) | |
| st.pyplot(fig, clear_figure=True) | |
| st.markdown(f"Constraint limit: {constraint_limit}") | |
| def panel(): | |
| step_1_complete = False | |
| step_2_complete = False | |
| step_3_complete = False | |
| structure_mask = {} | |
| tab1, tab2, tab3, tab4 = st.tabs( | |
| [ | |
| "🗃️Upload Data", | |
| "📊 View Dose Metrics", | |
| "🔍 Compute Compliance", | |
| "✅Evaluate Contour", | |
| ] | |
| ) | |
| with tab1: | |
| st.markdown(f"## Step 1: Upload dose distribution volume and mask files") | |
| st.markdown("Upload the dose volume:") | |
| dose_file = st.file_uploader( | |
| f"Upload dose volume: (in .nii.gz)", type=["nii", "gz"], key=0 | |
| ) | |
| st.markdown("Upload the contour masks:") | |
| mask_files = st.file_uploader( | |
| "Upload mask volumes (in .nii.gz)", | |
| accept_multiple_files=True, | |
| type=["nii", "gz"], | |
| key=1, | |
| ) | |
| files_uploaded = (dose_file is not None) and (len(mask_files) > 0) | |
| if files_uploaded: | |
| st.markdown( | |
| f"Both dose and mask files are uploaded. Click the toggle button below to proceed." | |
| ) | |
| step_1_complete = st.toggle("Compute") | |
| dose, _ = read_dose(dose_file) | |
| structure_mask = read_masks(mask_files) | |
| st.divider() | |
| with tab2: | |
| st.markdown(f"## Step 2: Dose Metrics") | |
| st.markdown(f"Complete Step 1 to view metrics.") | |
| if step_1_complete: | |
| st.markdown(f"Dose Metrics: contours, dose distribution.") | |
| dose_summary_df = display_summary(dose, structure_mask) | |
| csv = dose_summary_df.to_csv(index=False) | |
| st.download_button( | |
| label="Download CSV", | |
| data=csv, | |
| file_name=f"dose_summary_df.csv", | |
| mime="text/csv", | |
| key=999, | |
| ) | |
| st.divider() | |
| step_2_complete = True | |
| with tab3: | |
| st.markdown(f"## Step 3: Display Compliance") | |
| st.markdown(f"Complete Step 2 to proceed.") | |
| if step_2_complete: | |
| st.markdown(f"Clinical Compliance: contours, dose distribution.") | |
| compliance_results = compute_mirage_compliance(dose, structure_mask) | |
| st.table(compliance_results) | |
| compliance_csv = compliance_results.to_csv(index=True) | |
| st.download_button( | |
| label="Download compliance CSV", | |
| data=compliance_csv, | |
| file_name="compliance.csv", | |
| mime="text/csv", | |
| key=500, | |
| ) | |
| st.divider() | |
| step_3_complete = True | |
| with tab4: | |
| st.markdown(f"## Step 4: Check Contour Error Impact") | |
| st.markdown(f"Complete Step 3 to proceed.") | |
| if step_3_complete: | |
| st.markdown(f"Contour quality check: dice versus dose distribution.") | |
| constraints = get_custom_constraints() | |
| option = st.pills( | |
| "Choose structure:", | |
| tuple(structure_mask.keys()), | |
| selection_mode="single", | |
| ) | |
| st.divider() | |
| if option is not None: | |
| generate_dvh_family(dose, structure_mask, constraints, option) | |