Vamsi Thiriveedhi
commited on
Commit
·
918617e
1
Parent(s):
72491f8
remove vertebra check
Browse filesadd volume check
download parquet file from github instead of hf
- Dockerfile +3 -0
- filter_data_app.py +23 -21
- qual-checks-and-quant-values.parquet +0 -3
Dockerfile
CHANGED
|
@@ -20,6 +20,9 @@ RUN pip install --no-cache-dir --upgrade pip
|
|
| 20 |
# Copy the current directory contents into the container at $HOME/app setting the owner to the user
|
| 21 |
COPY --chown=user . $HOME/app
|
| 22 |
|
|
|
|
|
|
|
|
|
|
| 23 |
# Install any needed packages specified in requirements.txt
|
| 24 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 25 |
|
|
|
|
| 20 |
# Copy the current directory contents into the container at $HOME/app setting the owner to the user
|
| 21 |
COPY --chown=user . $HOME/app
|
| 22 |
|
| 23 |
+
# Download the parquet file from github
|
| 24 |
+
RUN wget https://github.com/ImagingDataCommons/CloudSegmentatorResults/releases/download/0.0.1/qual_checks_and_quantitative_measurements-wip.parquet
|
| 25 |
+
|
| 26 |
# Install any needed packages specified in requirements.txt
|
| 27 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 28 |
|
filter_data_app.py
CHANGED
|
@@ -12,19 +12,19 @@ import seaborn as sns
|
|
| 12 |
st.set_page_config(layout="wide")
|
| 13 |
|
| 14 |
# Local path to the Parquet file
|
| 15 |
-
LOCAL_PARQUET_FILE = '
|
| 16 |
|
| 17 |
@st.cache_data
|
| 18 |
def load_data(radiomics_feature='Volume from Voxel Summation'):
|
| 19 |
cols = [
|
| 20 |
'PatientID',
|
| 21 |
'StudyInstanceUID',
|
| 22 |
-
'
|
| 23 |
'bodyPart',
|
| 24 |
'laterality',
|
| 25 |
'segmentation_completeness',
|
| 26 |
'laterality_check',
|
| 27 |
-
'
|
| 28 |
'connected_volumes',
|
| 29 |
'voxel_num',
|
| 30 |
radiomics_feature # Include the selected radiomics feature column
|
|
@@ -62,7 +62,7 @@ def create_upset_plot_failures(df):
|
|
| 62 |
|
| 63 |
# Treat 'pass' and null values as passing
|
| 64 |
df = df.set_index(~((df['segmentation_completeness'] == 'pass') | df['segmentation_completeness'].isnull())).set_index(~((df['laterality_check'] == 'pass') | df['laterality_check'].isnull()), append=True)
|
| 65 |
-
df = df.set_index(~((df['
|
| 66 |
df = df.set_index(~((df['connected_volumes'] == 1) | df['connected_volumes'].isnull()), append=True)
|
| 67 |
df = df[df.index.to_frame().any(axis=1)] # Ignore the case when all conditions are false
|
| 68 |
|
|
@@ -75,7 +75,7 @@ def create_upset_plot_failures(df):
|
|
| 75 |
def create_upset_plot_passes(df):
|
| 76 |
df = df.to_pandas() # Convert to Pandas DataFrame
|
| 77 |
df = df.set_index(df['segmentation_completeness'] == 'pass').set_index(df['laterality_check'] == 'pass', append=True)
|
| 78 |
-
df = df.set_index(df['
|
| 79 |
df = df.set_index(df['connected_volumes'] == 1, append=True)
|
| 80 |
df = df[df.index.to_frame().any(axis=1)] # Ignore the case when all conditions are false
|
| 81 |
|
|
@@ -96,7 +96,7 @@ def main():
|
|
| 96 |
st.title("Qualitative Checks of TotalSegmentator Segmentations on NLST")
|
| 97 |
|
| 98 |
# Sidebar widgets for navigation and filtering
|
| 99 |
-
page = st.sidebar.selectbox("Choose a page", ["Summary", "Plots"])
|
| 100 |
|
| 101 |
# Load the data
|
| 102 |
#df = load_data()
|
|
@@ -112,7 +112,7 @@ def main():
|
|
| 112 |
'bodyPart': None,
|
| 113 |
'segmentation_completeness': None,
|
| 114 |
'laterality_check': None,
|
| 115 |
-
'
|
| 116 |
'connected_volumes': None,
|
| 117 |
'laterality': None,
|
| 118 |
'radiomics_feature': 'Volume from Voxel Summation', # Default radiomics feature
|
|
@@ -127,7 +127,7 @@ def main():
|
|
| 127 |
filters.update({
|
| 128 |
'segmentation_completeness': None,
|
| 129 |
'laterality_check': None,
|
| 130 |
-
'
|
| 131 |
'connected_volumes': None,
|
| 132 |
'laterality': None,
|
| 133 |
#'radiomics_feature': 'Volume from Voxel Summation'
|
|
@@ -195,7 +195,7 @@ def main():
|
|
| 195 |
# Update options for other filters based on the current selection
|
| 196 |
segmentation_completeness_options = [""] + filtered_df['segmentation_completeness'].unique().to_list()
|
| 197 |
laterality_check_options = [""] + filtered_df['laterality_check'].unique().to_list()
|
| 198 |
-
|
| 199 |
connected_volumes_options = filtered_df['connected_volumes'].unique().to_list()
|
| 200 |
laterality_options = [""] + filtered_df['laterality'].unique().to_list()
|
| 201 |
voxel_num_options = filtered_df.filter(col('voxel_num').is_not_null()).select('voxel_num').unique().to_pandas().iloc[:, 0].tolist()
|
|
@@ -226,12 +226,12 @@ def main():
|
|
| 226 |
on_change=lambda: apply_filter('laterality_check', st.session_state.laterality_check)
|
| 227 |
)
|
| 228 |
|
| 229 |
-
|
| 230 |
-
"
|
| 231 |
-
options=
|
| 232 |
-
index=
|
| 233 |
-
key='
|
| 234 |
-
on_change=lambda: apply_filter('
|
| 235 |
)
|
| 236 |
|
| 237 |
connected_volumes = st.selectbox(
|
|
@@ -249,6 +249,7 @@ def main():
|
|
| 249 |
value=(min(voxel_num_options),max(voxel_num_options)),
|
| 250 |
on_change=lambda: apply_filter('voxel_num_values', st.session_state.voxel_num_values)
|
| 251 |
)
|
|
|
|
| 252 |
if min(radiomics_feature_values)!=max(radiomics_feature_values):
|
| 253 |
radiomics_num_values = st.slider(f"{radiomics_feature} Values",
|
| 254 |
min_value=min(radiomics_feature_values),
|
|
@@ -291,6 +292,7 @@ def main():
|
|
| 291 |
start_idx = (page_number - 1) * page_size
|
| 292 |
end_idx = min(start_idx + page_size, len(filtered_df)) # Ensure end_idx does not go beyond the dataframe length
|
| 293 |
paginated_df = filtered_df[start_idx:end_idx].to_pandas() # Convert to Pandas DataFrame
|
|
|
|
| 294 |
paginated_df['Viewer Url'] = 'https://viewer.imaging.datacommons.cancer.gov/v3/viewer/?StudyInstanceUIDs='+paginated_df['StudyInstanceUID']
|
| 295 |
|
| 296 |
# Display the paginated dataframe
|
|
@@ -302,10 +304,10 @@ def main():
|
|
| 302 |
column_config={
|
| 303 |
"Viewer Url":st.column_config.LinkColumn("StudyInstanceUID",
|
| 304 |
display_text=r"https:\/\/viewer\.imaging\.datacommons\.cancer\.gov\/v3\/viewer\/\?StudyInstanceUIDs=(.*)"
|
| 305 |
-
),
|
| 306 |
|
| 307 |
},
|
| 308 |
-
column_order=("PatientID", "Viewer Url", "
|
| 309 |
hide_index=True,
|
| 310 |
use_container_width=True
|
| 311 |
)
|
|
@@ -379,10 +381,10 @@ def main():
|
|
| 379 |
SUM(CASE WHEN segmentation_completeness = 'pass' THEN 1 ELSE 0 END) AS pass_count,
|
| 380 |
SUM(CASE WHEN laterality_check = 'pass' THEN 1 ELSE 0 END) AS laterality_pass_count,
|
| 381 |
SUM(CASE WHEN laterality_check is not null THEN 1 ELSE 0 END) AS laterality_check_total_count,
|
| 382 |
-
SUM(CASE WHEN
|
| 383 |
SUM(CASE WHEN connected_volumes = '1' THEN 1 ELSE 0 END) AS volumes_pass_count
|
| 384 |
FROM
|
| 385 |
-
'
|
| 386 |
GROUP BY
|
| 387 |
bodyPart, laterality
|
| 388 |
)
|
|
@@ -394,8 +396,8 @@ def main():
|
|
| 394 |
CASE WHEN laterality IS NOT NULL
|
| 395 |
THEN ROUND((laterality_pass_count * 100.0) / NULLIF(laterality_check_total_count, 0), 2) || '% (' || laterality_pass_count || '/' || laterality_check_total_count || ')'
|
| 396 |
ELSE 'N/A' END AS laterality_check,
|
| 397 |
-
ROUND((
|
| 398 |
-
ROUND((volumes_pass_count * 100.0) / total_count, 2) || '% (' || volumes_pass_count || '/' || total_count || ')' AS
|
| 399 |
FROM
|
| 400 |
Checks
|
| 401 |
ORDER BY
|
|
|
|
| 12 |
st.set_page_config(layout="wide")
|
| 13 |
|
| 14 |
# Local path to the Parquet file
|
| 15 |
+
LOCAL_PARQUET_FILE = 'qual_checks_and_quantitative_measurements-wip.parquet'
|
| 16 |
|
| 17 |
@st.cache_data
|
| 18 |
def load_data(radiomics_feature='Volume from Voxel Summation'):
|
| 19 |
cols = [
|
| 20 |
'PatientID',
|
| 21 |
'StudyInstanceUID',
|
| 22 |
+
'SeriesNumber',
|
| 23 |
'bodyPart',
|
| 24 |
'laterality',
|
| 25 |
'segmentation_completeness',
|
| 26 |
'laterality_check',
|
| 27 |
+
'volume_from_voxel_summation_check',
|
| 28 |
'connected_volumes',
|
| 29 |
'voxel_num',
|
| 30 |
radiomics_feature # Include the selected radiomics feature column
|
|
|
|
| 62 |
|
| 63 |
# Treat 'pass' and null values as passing
|
| 64 |
df = df.set_index(~((df['segmentation_completeness'] == 'pass') | df['segmentation_completeness'].isnull())).set_index(~((df['laterality_check'] == 'pass') | df['laterality_check'].isnull()), append=True)
|
| 65 |
+
df = df.set_index(~((df['volume_from_voxel_summation_check'] == 'pass') | df['volume_from_voxel_summation_check'].isnull()), append=True)
|
| 66 |
df = df.set_index(~((df['connected_volumes'] == 1) | df['connected_volumes'].isnull()), append=True)
|
| 67 |
df = df[df.index.to_frame().any(axis=1)] # Ignore the case when all conditions are false
|
| 68 |
|
|
|
|
| 75 |
def create_upset_plot_passes(df):
|
| 76 |
df = df.to_pandas() # Convert to Pandas DataFrame
|
| 77 |
df = df.set_index(df['segmentation_completeness'] == 'pass').set_index(df['laterality_check'] == 'pass', append=True)
|
| 78 |
+
df = df.set_index(df['volume_from_voxel_summation_check'] == 'pass', append=True)
|
| 79 |
df = df.set_index(df['connected_volumes'] == 1, append=True)
|
| 80 |
df = df[df.index.to_frame().any(axis=1)] # Ignore the case when all conditions are false
|
| 81 |
|
|
|
|
| 96 |
st.title("Qualitative Checks of TotalSegmentator Segmentations on NLST")
|
| 97 |
|
| 98 |
# Sidebar widgets for navigation and filtering
|
| 99 |
+
page = st.sidebar.selectbox("Choose a page", ["Summary", "Plots"], help='Change the selection here to view dynamically generated plots')
|
| 100 |
|
| 101 |
# Load the data
|
| 102 |
#df = load_data()
|
|
|
|
| 112 |
'bodyPart': None,
|
| 113 |
'segmentation_completeness': None,
|
| 114 |
'laterality_check': None,
|
| 115 |
+
'volume_from_voxel_summation_check': None,
|
| 116 |
'connected_volumes': None,
|
| 117 |
'laterality': None,
|
| 118 |
'radiomics_feature': 'Volume from Voxel Summation', # Default radiomics feature
|
|
|
|
| 127 |
filters.update({
|
| 128 |
'segmentation_completeness': None,
|
| 129 |
'laterality_check': None,
|
| 130 |
+
'volume_from_voxel_summation_check': None,
|
| 131 |
'connected_volumes': None,
|
| 132 |
'laterality': None,
|
| 133 |
#'radiomics_feature': 'Volume from Voxel Summation'
|
|
|
|
| 195 |
# Update options for other filters based on the current selection
|
| 196 |
segmentation_completeness_options = [""] + filtered_df['segmentation_completeness'].unique().to_list()
|
| 197 |
laterality_check_options = [""] + filtered_df['laterality_check'].unique().to_list()
|
| 198 |
+
volume_from_voxel_summation_check_options = [""] + filtered_df['volume_from_voxel_summation_check'].unique().to_list()
|
| 199 |
connected_volumes_options = filtered_df['connected_volumes'].unique().to_list()
|
| 200 |
laterality_options = [""] + filtered_df['laterality'].unique().to_list()
|
| 201 |
voxel_num_options = filtered_df.filter(col('voxel_num').is_not_null()).select('voxel_num').unique().to_pandas().iloc[:, 0].tolist()
|
|
|
|
| 226 |
on_change=lambda: apply_filter('laterality_check', st.session_state.laterality_check)
|
| 227 |
)
|
| 228 |
|
| 229 |
+
volume_from_voxel_summation_check = st.selectbox(
|
| 230 |
+
"Minimum Volume of 5 mL",
|
| 231 |
+
options=volume_from_voxel_summation_check_options,
|
| 232 |
+
index=volume_from_voxel_summation_check_options.index(filters['volume_from_voxel_summation_check']) if filters['volume_from_voxel_summation_check'] else 0,
|
| 233 |
+
key='volume_from_voxel_summation_check',
|
| 234 |
+
on_change=lambda: apply_filter('volume_from_voxel_summation_check', st.session_state.volume_from_voxel_summation_check)
|
| 235 |
)
|
| 236 |
|
| 237 |
connected_volumes = st.selectbox(
|
|
|
|
| 249 |
value=(min(voxel_num_options),max(voxel_num_options)),
|
| 250 |
on_change=lambda: apply_filter('voxel_num_values', st.session_state.voxel_num_values)
|
| 251 |
)
|
| 252 |
+
|
| 253 |
if min(radiomics_feature_values)!=max(radiomics_feature_values):
|
| 254 |
radiomics_num_values = st.slider(f"{radiomics_feature} Values",
|
| 255 |
min_value=min(radiomics_feature_values),
|
|
|
|
| 292 |
start_idx = (page_number - 1) * page_size
|
| 293 |
end_idx = min(start_idx + page_size, len(filtered_df)) # Ensure end_idx does not go beyond the dataframe length
|
| 294 |
paginated_df = filtered_df[start_idx:end_idx].to_pandas() # Convert to Pandas DataFrame
|
| 295 |
+
paginated_df = paginated_df.rename(columns={"connected_volumes": "connected_components"})
|
| 296 |
paginated_df['Viewer Url'] = 'https://viewer.imaging.datacommons.cancer.gov/v3/viewer/?StudyInstanceUIDs='+paginated_df['StudyInstanceUID']
|
| 297 |
|
| 298 |
# Display the paginated dataframe
|
|
|
|
| 304 |
column_config={
|
| 305 |
"Viewer Url":st.column_config.LinkColumn("StudyInstanceUID",
|
| 306 |
display_text=r"https:\/\/viewer\.imaging\.datacommons\.cancer\.gov\/v3\/viewer\/\?StudyInstanceUIDs=(.*)"
|
| 307 |
+
),
|
| 308 |
|
| 309 |
},
|
| 310 |
+
column_order=("PatientID", "Viewer Url", "SeriesNumber","bodyPart","laterality", "segmentation_completeness","laterality_check", "volume_from_voxel_summation_check","connected_components","voxel_num", radiomics_feature),
|
| 311 |
hide_index=True,
|
| 312 |
use_container_width=True
|
| 313 |
)
|
|
|
|
| 381 |
SUM(CASE WHEN segmentation_completeness = 'pass' THEN 1 ELSE 0 END) AS pass_count,
|
| 382 |
SUM(CASE WHEN laterality_check = 'pass' THEN 1 ELSE 0 END) AS laterality_pass_count,
|
| 383 |
SUM(CASE WHEN laterality_check is not null THEN 1 ELSE 0 END) AS laterality_check_total_count,
|
| 384 |
+
SUM(CASE WHEN volume_from_voxel_summation_check = 'pass' THEN 1 ELSE 0 END) AS volume_check_pass_count,
|
| 385 |
SUM(CASE WHEN connected_volumes = '1' THEN 1 ELSE 0 END) AS volumes_pass_count
|
| 386 |
FROM
|
| 387 |
+
'qual_checks_and_quantitative_measurements-wip.parquet'
|
| 388 |
GROUP BY
|
| 389 |
bodyPart, laterality
|
| 390 |
)
|
|
|
|
| 396 |
CASE WHEN laterality IS NOT NULL
|
| 397 |
THEN ROUND((laterality_pass_count * 100.0) / NULLIF(laterality_check_total_count, 0), 2) || '% (' || laterality_pass_count || '/' || laterality_check_total_count || ')'
|
| 398 |
ELSE 'N/A' END AS laterality_check,
|
| 399 |
+
ROUND((volume_check_pass_count * 100.0) / total_count, 2) || '% (' || volume_check_pass_count || '/' || total_count || ')' AS volume_check_pass_count,
|
| 400 |
+
ROUND((volumes_pass_count * 100.0) / total_count, 2) || '% (' || volumes_pass_count || '/' || total_count || ')' AS connected_components_check
|
| 401 |
FROM
|
| 402 |
Checks
|
| 403 |
ORDER BY
|
qual-checks-and-quant-values.parquet
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:9cdb5ac665c8bedf906f07ba1ba05232cf9ab2eb9045caec7fa1a3343222e9f2
|
| 3 |
-
size 1157730459
|
|
|
|
|
|
|
|
|
|
|
|