Vamsi Thiriveedhi commited on
Commit
d7e211f
·
1 Parent(s): 2c67485

enh: slider to filter radiomics features values, move violin plots to top

Browse files
Files changed (1) hide show
  1. filter_data_app.py +40 -27
filter_data_app.py CHANGED
@@ -39,13 +39,15 @@ def load_data(radiomics_feature='Volume from Voxel Summation'):
39
  return df
40
 
41
  # Function to filter data based on user input
42
- def filter_data(df, filters):
43
  for col, value in filters.items():
44
  if value is not None and col != 'radiomics_feature': # Exclude radiomics_feature from filtering
45
  if col == 'connected_volumes' and value:
46
  df = df.filter((pl.col(col) <= value) & (pl.col(col).is_not_null()))
47
  elif col == 'voxel_num_values' and value:
48
  df = df.filter((pl.col('voxel_num') >= value[0]) & (pl.col('voxel_num') <= value[1]))
 
 
49
  else:
50
  df = df.filter(pl.col(col) == value)
51
  # Filter based on radiomics feature
@@ -94,12 +96,12 @@ def main():
94
  st.title("Qualitative Checks of TotalSegmentator Segmentations on NLST")
95
 
96
  # Sidebar widgets for navigation and filtering
97
- page = st.sidebar.selectbox("Choose a page", ["Summary", "UpSet Plots"])
98
 
99
  # Load the data
100
  #df = load_data()
101
 
102
- if page == "UpSet Plots":
103
  st.write("Filter the data based on radiomics feature, qualitative checks, bodyPart, and laterality.")
104
  with st.sidebar:
105
  st.title("Filters")
@@ -114,7 +116,8 @@ def main():
114
  'connected_volumes': None,
115
  'laterality': None,
116
  'radiomics_feature': 'Volume from Voxel Summation', # Default radiomics feature
117
- 'voxel_num_values': None
 
118
  }
119
 
120
  filters = st.session_state.filters
@@ -129,6 +132,7 @@ def main():
129
  'laterality': None,
130
  #'radiomics_feature': 'Volume from Voxel Summation'
131
  'voxel_num_values':None,
 
132
  })
133
  st.session_state.filters = filters
134
 
@@ -185,7 +189,7 @@ def main():
185
  filters['bodyPart'] = body_part
186
 
187
  # Apply the current filters to update options for other filters
188
- filtered_df = filter_data(df, filters)
189
 
190
 
191
  # Update options for other filters based on the current selection
@@ -195,6 +199,7 @@ def main():
195
  connected_volumes_options = filtered_df['connected_volumes'].unique().to_list()
196
  laterality_options = [""] + filtered_df['laterality'].unique().to_list()
197
  voxel_num_options = filtered_df.filter(col('voxel_num').is_not_null()).select('voxel_num').unique().to_pandas().iloc[:, 0].tolist()
 
198
 
199
  laterality = st.selectbox(
200
  "Laterality",
@@ -244,9 +249,16 @@ def main():
244
  value=(min(voxel_num_options),max(voxel_num_options)),
245
  on_change=lambda: apply_filter('voxel_num_values', st.session_state.voxel_num_values)
246
  )
 
 
 
 
 
 
 
247
 
248
  st.session_state.filters = filters
249
- filtered_df = filter_data(df, filters)
250
 
251
  if laterality:
252
  body_part_df = df.filter((col('bodyPart') == lit(body_part)) & (col('laterality') == lit(laterality)))
@@ -278,7 +290,7 @@ def main():
278
  start_idx = (page_number - 1) * page_size
279
  end_idx = min(start_idx + page_size, len(filtered_df)) # Ensure end_idx does not go beyond the dataframe length
280
  paginated_df = filtered_df[start_idx:end_idx].to_pandas() # Convert to Pandas DataFrame
281
- paginated_df['Viewer Url'] = 'https://viewer.imaging.datacommons.cancer.gov/viewer/'+paginated_df['StudyInstanceUID']
282
 
283
  # Display the paginated dataframe
284
  st.header("Filtered Data")
@@ -288,7 +300,7 @@ def main():
288
  paginated_df,
289
  column_config={
290
  "Viewer Url":st.column_config.LinkColumn("StudyInstanceUID",
291
- display_text=r"https:\/\/viewer\.imaging\.datacommons\.cancer\.gov\/viewer\/(.*)"
292
  ),
293
 
294
  },
@@ -296,25 +308,6 @@ def main():
296
  hide_index=True,
297
  use_container_width=True
298
  )
299
- st.header("UpSet Plots of Qualitative Checks")
300
- # Explanation about the UpSet plot
301
- with st.expander("About the UpSet Plot"):
302
- st.write("""
303
- The UpSet plot is a way to visualize intersections of multiple sets. Each row in the plot represents a different set, and the dots indicate the presence or absence of intersections among these sets. The vertical bars show the size of each intersection, making it easy to see which intersections are most common.
304
- """)
305
-
306
- # Create and display the UpSet plot for failed checks
307
- st.header("UpSet Plot for Failed Checks")
308
- st.write("This plot shows the combinations of checks that failed.")
309
- if not filtered_df.is_empty():
310
- create_upset_plot_failures(filtered_df)
311
-
312
- # Create and display the UpSet plot for passed checks
313
- st.header("UpSet Plot for Passed Checks")
314
- st.write("This plot shows the combinations of checks that passed.")
315
- if not filtered_df.is_empty():
316
- create_upset_plot_passes(filtered_df)
317
-
318
  # Assuming calculate_std_dev returns a Series
319
  std_dev_before_filtering = calculate_std_dev(body_part_df, radiomics_feature)
320
  std_dev_after_filtering = calculate_std_dev(filtered_df, radiomics_feature)
@@ -339,6 +332,26 @@ def main():
339
  sns.violinplot(x='Filtering', y=radiomics_feature, data=combined_df, ax=ax)
340
  ax.set_ylabel(f"Standard Deviation of {radiomics_feature}")
341
  st.pyplot(fig2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
 
343
  def convert_df(df):
344
  return df.write_csv()
 
39
  return df
40
 
41
  # Function to filter data based on user input
42
+ def filter_data(df, filters,radiomics_feature):
43
  for col, value in filters.items():
44
  if value is not None and col != 'radiomics_feature': # Exclude radiomics_feature from filtering
45
  if col == 'connected_volumes' and value:
46
  df = df.filter((pl.col(col) <= value) & (pl.col(col).is_not_null()))
47
  elif col == 'voxel_num_values' and value:
48
  df = df.filter((pl.col('voxel_num') >= value[0]) & (pl.col('voxel_num') <= value[1]))
49
+ elif col == 'radiomics_feature_values' and value:
50
+ df = df.filter((pl.col(radiomics_feature) >= value[0]) & (pl.col(radiomics_feature) <= value[1]))
51
  else:
52
  df = df.filter(pl.col(col) == value)
53
  # Filter based on radiomics feature
 
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()
103
 
104
+ if page == "Plots":
105
  st.write("Filter the data based on radiomics feature, qualitative checks, bodyPart, and laterality.")
106
  with st.sidebar:
107
  st.title("Filters")
 
116
  'connected_volumes': None,
117
  'laterality': None,
118
  'radiomics_feature': 'Volume from Voxel Summation', # Default radiomics feature
119
+ 'voxel_num_values': None,
120
+ 'radiomics_feature_values': None
121
  }
122
 
123
  filters = st.session_state.filters
 
132
  'laterality': None,
133
  #'radiomics_feature': 'Volume from Voxel Summation'
134
  'voxel_num_values':None,
135
+ 'radiomics_feature_values': None
136
  })
137
  st.session_state.filters = filters
138
 
 
189
  filters['bodyPart'] = body_part
190
 
191
  # Apply the current filters to update options for other filters
192
+ filtered_df = filter_data(df, filters,radiomics_feature)
193
 
194
 
195
  # Update options for other filters based on the current selection
 
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()
202
+ radiomics_feature_values = filtered_df.filter(col(radiomics_feature).is_not_null()).select(radiomics_feature).unique().to_pandas().iloc[:, 0].tolist()
203
 
204
  laterality = st.selectbox(
205
  "Laterality",
 
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
+ radiomics_num_values = st.slider(f"{radiomics_feature} Values",
253
+ min_value=min(radiomics_feature_values),
254
+ max_value=max(radiomics_feature_values),
255
+ key='radiomics_feature_values',
256
+ value=(min(radiomics_feature_values),max(radiomics_feature_values)),
257
+ on_change=lambda: apply_filter('radiomics_feature_values', st.session_state.radiomics_feature_values)
258
+ )
259
 
260
  st.session_state.filters = filters
261
+ filtered_df = filter_data(df, filters,radiomics_feature)
262
 
263
  if laterality:
264
  body_part_df = df.filter((col('bodyPart') == lit(body_part)) & (col('laterality') == lit(laterality)))
 
290
  start_idx = (page_number - 1) * page_size
291
  end_idx = min(start_idx + page_size, len(filtered_df)) # Ensure end_idx does not go beyond the dataframe length
292
  paginated_df = filtered_df[start_idx:end_idx].to_pandas() # Convert to Pandas DataFrame
293
+ paginated_df['Viewer Url'] = 'https://viewer.imaging.datacommons.cancer.gov/v3/viewer/?StudyInstanceUIDs='+paginated_df['StudyInstanceUID']
294
 
295
  # Display the paginated dataframe
296
  st.header("Filtered Data")
 
300
  paginated_df,
301
  column_config={
302
  "Viewer Url":st.column_config.LinkColumn("StudyInstanceUID",
303
+ display_text=r"https:\/\/viewer\.imaging\.datacommons\.cancer\.gov\/v3\/viewer\/\?StudyInstanceUIDs=(.*)"
304
  ),
305
 
306
  },
 
308
  hide_index=True,
309
  use_container_width=True
310
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  # Assuming calculate_std_dev returns a Series
312
  std_dev_before_filtering = calculate_std_dev(body_part_df, radiomics_feature)
313
  std_dev_after_filtering = calculate_std_dev(filtered_df, radiomics_feature)
 
332
  sns.violinplot(x='Filtering', y=radiomics_feature, data=combined_df, ax=ax)
333
  ax.set_ylabel(f"Standard Deviation of {radiomics_feature}")
334
  st.pyplot(fig2)
335
+
336
+
337
+ st.header("UpSet Plots of Qualitative Checks")
338
+ # Explanation about the UpSet plot
339
+ with st.expander("About the UpSet Plot"):
340
+ st.write("""
341
+ The UpSet plot is a way to visualize intersections of multiple sets. Each row in the plot represents a different set, and the dots indicate the presence or absence of intersections among these sets. The vertical bars show the size of each intersection, making it easy to see which intersections are most common.
342
+ """)
343
+
344
+ # Create and display the UpSet plot for failed checks
345
+ st.header("UpSet Plot for Failed Checks")
346
+ st.write("This plot shows the combinations of checks that failed.")
347
+ if not filtered_df.is_empty():
348
+ create_upset_plot_failures(filtered_df)
349
+
350
+ # Create and display the UpSet plot for passed checks
351
+ st.header("UpSet Plot for Passed Checks")
352
+ st.write("This plot shows the combinations of checks that passed.")
353
+ if not filtered_df.is_empty():
354
+ create_upset_plot_passes(filtered_df)
355
 
356
  def convert_df(df):
357
  return df.write_csv()