Spaces:
Sleeping
Sleeping
Update app.py
#1
by
gzsbwfj03
- opened
app.py
CHANGED
|
@@ -1,6 +1,3 @@
|
|
| 1 |
-
# give some time reference to the user
|
| 2 |
-
print('Importing Gradio app packages... (first launch takes about 3-5 minutes)')
|
| 3 |
-
|
| 4 |
import gradio as gr
|
| 5 |
import yaml
|
| 6 |
import skimage
|
|
@@ -334,42 +331,111 @@ def viz_cluster_positive(marker, percentile_threshold, cytof_img, cytof_cohort):
|
|
| 334 |
return fig, cytof_img, cytof_cohort
|
| 335 |
|
| 336 |
# Gradio App template
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 347 |
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 351 |
|
| 352 |
with gr.Row(equal_height=True): # second row where 1) asks for marker file upload and 2) displays the visualization of individual channels
|
| 353 |
-
with gr.Column():
|
| 354 |
-
|
|
|
|
|
|
|
| 355 |
with gr.Row():
|
| 356 |
clear_btn = gr.Button("Clear")
|
| 357 |
submit_btn = gr.Button("Upload")
|
| 358 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 359 |
|
| 360 |
-
gr.Markdown("# Step 2. Modify existing channels")
|
| 361 |
-
gr.Markdown("After visualizing the individual channels, did you notice any that should not be included in the next steps? Remove those if so.")
|
| 362 |
-
gr.Markdown("Define channels designed to visualize nuclei. Optionally, define channels designed to visualize membranes.")
|
| 363 |
-
|
| 364 |
with gr.Row(equal_height=True): # third row selects nuclei channels
|
| 365 |
-
with gr.Column():
|
| 366 |
-
selected_unwanted_channel = gr.Dropdown(label='(Optional) Select the unwanted channel', interactive=True)
|
| 367 |
selected_nuclei = gr.Dropdown(label='(Required) Select the nuclei channel', interactive=True)
|
|
|
|
| 368 |
selected_membrane = gr.Dropdown(label='(Optional) Select the membrane channel', interactive=True)
|
| 369 |
-
|
| 370 |
define_btn = gr.Button('Modify channels')
|
| 371 |
-
|
| 372 |
-
|
| 373 |
|
| 374 |
# upload the file, and gather channel info. Then populate to the unwanted_channel, nuclei, and membrane components
|
| 375 |
submit_btn.click(
|
|
@@ -386,85 +452,132 @@ with gr.Blocks() as demo:
|
|
| 386 |
# modifies the channels per user input
|
| 387 |
define_btn.click(fn=modify_channels, inputs=[cytof_original_state, selected_unwanted_channel, selected_nuclei, selected_membrane], outputs=[channel_feedback, cytof_state])
|
| 388 |
|
| 389 |
-
gr.Markdown('
|
|
|
|
|
|
|
| 390 |
|
| 391 |
with gr.Row(): # This row defines cell radius and performs segmentation
|
| 392 |
-
with gr.Column():
|
| 393 |
-
|
|
|
|
| 394 |
seg_btn = gr.Button("Segment")
|
| 395 |
-
|
|
|
|
|
|
|
|
|
|
| 396 |
seg_btn.click(fn=cell_seg, inputs=[cytof_state, cell_radius], outputs=[seg_viz, cytof_state])
|
| 397 |
-
|
| 398 |
-
gr.Markdown('
|
|
|
|
|
|
|
| 399 |
|
| 400 |
cohort_state = gr.State(CytofCohort())
|
| 401 |
with gr.Row(): # feature extraction related functinos
|
| 402 |
-
with gr.Column():
|
| 403 |
-
gr.CheckboxGroup(choices=['Yes', 'Yes', 'Yes'], label='
|
| 404 |
norm_percentile = gr.Slider(minimum=50, maximum=99, step=1, value=75, interactive=True, label='Normalized quantification percentile')
|
| 405 |
extract_btn = gr.Button('Extract')
|
| 406 |
-
|
|
|
|
| 407 |
|
| 408 |
extract_btn.click(fn=feature_extraction, inputs=[cytof_state, cohort_state, norm_percentile],
|
| 409 |
outputs=[cytof_state, cohort_state, feat_df])
|
| 410 |
|
| 411 |
-
gr.Markdown('
|
| 412 |
-
|
|
|
|
|
|
|
| 413 |
with gr.Row(): # show co-expression and spatial analysis
|
| 414 |
-
with gr.Column():
|
| 415 |
-
|
| 416 |
co_exp_btn = gr.Button('Run co-expression analysis')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 417 |
|
| 418 |
-
|
| 419 |
-
spatial_viz = gr.Plot(label="Visualization of cell spatial interaction of markers")
|
| 420 |
-
cluster_method = gr.Radio(label='Select the clustering method', value='k-neighbor', choices=['k-neighbor', 'distance'], info='K-neighbor: classifies the threshold number of surrounding cells as neighborhood pairs. Distance: classifies cells within threshold distance as neighborhood pairs.')
|
| 421 |
-
cluster_threshold = gr.Slider(minimum=1, maximum=100, step=1, value=30, interactive=True, label='Clustering threshold')
|
| 422 |
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
|
|
|
| 427 |
|
| 428 |
-
gr.
|
| 429 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 430 |
|
| 431 |
with gr.Row(): # two marker positive visualization - dropdown options
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 436 |
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
fn=get_marker_pos_options, inputs=[cytof_state], outputs=[selected_marker1, selected_marker2]
|
| 444 |
-
)
|
| 445 |
-
pos_viz_btn.click(fn=viz_pos_marker_pair, inputs=[cytof_state, selected_marker1, selected_marker2, norm_percentile], outputs=[marker_pos_viz])
|
| 446 |
|
| 447 |
-
|
| 448 |
-
gr.Markdown('
|
| 449 |
-
gr.Markdown('Cells can be clustered into sub-groups based on the extracted single-cell data.
|
| 450 |
|
| 451 |
with gr.Row(): # add two plots to visualize phenograph results
|
| 452 |
-
|
| 453 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 454 |
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 459 |
cluster_interact_btn.click(cluster_interaction_fn, inputs=[cytof_state, cohort_state], outputs=[cluster_interaction, cytof_state, cohort_state])
|
| 460 |
|
|
|
|
|
|
|
|
|
|
| 461 |
with gr.Row():
|
| 462 |
-
with gr.Column():
|
| 463 |
selected_cluster_marker = gr.Dropdown(label='Select one marker', info='Select a marker to visualize', interactive=True)
|
| 464 |
cluster_positive_btn = gr.Button('Compare clusters and positive markers')
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
|
|
|
|
| 468 |
|
| 469 |
|
| 470 |
umap_btn.click(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import yaml
|
| 3 |
import skimage
|
|
|
|
| 331 |
return fig, cytof_img, cytof_cohort
|
| 332 |
|
| 333 |
# Gradio App template
|
| 334 |
+
custom_css = """
|
| 335 |
+
<style>
|
| 336 |
+
.h-1 {
|
| 337 |
+
font-size: 40px !important;
|
| 338 |
+
}
|
| 339 |
+
.h-2 {
|
| 340 |
+
font-size: 20px !important;
|
| 341 |
+
}
|
| 342 |
+
.h-3 {
|
| 343 |
+
font-size: 20px !important;
|
| 344 |
+
}
|
| 345 |
+
.mb-10 {
|
| 346 |
+
margin-bottom: 10px !important;
|
| 347 |
+
}
|
| 348 |
+
.no-label label {
|
| 349 |
+
display: none !important;
|
| 350 |
+
}
|
| 351 |
+
.cell-no-label span {
|
| 352 |
+
display: none !important;
|
| 353 |
+
}
|
| 354 |
+
.no-border {
|
| 355 |
+
border-width: 0 !important;
|
| 356 |
+
}
|
| 357 |
+
hr {
|
| 358 |
+
margin: 1.5rem 0 0 0 !important;
|
| 359 |
+
padding-bottom: 10px !important;
|
| 360 |
+
}
|
| 361 |
+
.input-choices {
|
| 362 |
+
padding: 10px 0 !important;
|
| 363 |
+
}
|
| 364 |
+
.input-choices > span {
|
| 365 |
+
display: none;
|
| 366 |
+
}
|
| 367 |
+
.form:has(.input-choices) {
|
| 368 |
+
border-width: 0 !important;
|
| 369 |
+
box-shadow: none !important;
|
| 370 |
+
}
|
| 371 |
+
.bold {
|
| 372 |
+
font-weight: 600 !important;
|
| 373 |
+
}
|
| 374 |
+
</style>
|
| 375 |
+
"""
|
| 376 |
|
| 377 |
+
with gr.Blocks() as demo:
|
| 378 |
+
gr.HTML(custom_css)
|
| 379 |
+
|
| 380 |
+
gr.Markdown('<div class="h-1">Step 1. Upload images</div>')
|
| 381 |
+
gr.Markdown('<div class="h-2">You may upload one or two files depending on your use case.</div>')
|
| 382 |
+
gr.Markdown('<div class="h-2 bold">Case 1: Upload a single file</div>')
|
| 383 |
+
gr.Markdown('<div class="h-2"><ul><li>upload a TXT or CSV file that contains information about antibodies, rare heavy metal isotopes, and image channel names.</li>'
|
| 384 |
+
'<li>files are following the CyTOF, IMC, or multiplex data convention.</li>'
|
| 385 |
+
'</ul></div>')
|
| 386 |
+
gr.Markdown('<div class="h-2 bold">Case 2: Upload multiple files</div>')
|
| 387 |
+
gr.Markdown('<div class="h-2"><ul><li>upload a TIFF file containing Regions of Interest (ROIs) stored as multiplexed images. <a href="https://qbrc.swmed.edu/labs/xiaoxie/download/multiplex/example_image.tiff" download target="_blank">Example ROI</a></li>'
|
| 388 |
+
'<li>upload a Marker File listing the channels to identify the antibodies. <a href="https://github.com/QBRC/multiTAP/blob/main/example_data/markers_labels.txt" download target="_blank">Example Marker File</a></li>'
|
| 389 |
+
'</ul></div><hr>')
|
| 390 |
+
|
| 391 |
+
gr.Markdown('<div class="h-2">Select Input Case:</div>')
|
| 392 |
+
|
| 393 |
+
choices = gr.Radio(["Case 1", "Case 2"], value="Case 1", label="Choose Input Case", elem_classes='input-choices')
|
| 394 |
+
|
| 395 |
+
def toggle_file_input(choice):
|
| 396 |
+
if choice == "Case 1":
|
| 397 |
+
return (
|
| 398 |
+
gr.update(visible=True, file_types=['.txt', '.csv'], label="TXT or CSV File"),
|
| 399 |
+
gr.update(visible=False)
|
| 400 |
+
)
|
| 401 |
+
else:
|
| 402 |
+
return (
|
| 403 |
+
gr.update(visible=True, file_types=[".tiff", '.tif'], label="TIFF File"),
|
| 404 |
+
gr.update(visible=True)
|
| 405 |
+
)
|
| 406 |
|
| 407 |
with gr.Row(equal_height=True): # second row where 1) asks for marker file upload and 2) displays the visualization of individual channels
|
| 408 |
+
with gr.Column(scale=2):
|
| 409 |
+
gr.Markdown('<div class="h-2">File Input:</div>')
|
| 410 |
+
img_path = gr.File(file_types=['.txt', '.csv'], label='TXT or CSV File')
|
| 411 |
+
marker_path = gr.File(file_types=['.txt'], label='Marker File', visible=False)
|
| 412 |
with gr.Row():
|
| 413 |
clear_btn = gr.Button("Clear")
|
| 414 |
submit_btn = gr.Button("Upload")
|
| 415 |
+
with gr.Column(scale=3):
|
| 416 |
+
gr.Markdown('<div class="h-2">Marker Information:</div>')
|
| 417 |
+
img_info = gr.Textbox(label='Ensure the number of markers displayed below matches the expected number.')
|
| 418 |
+
gr.Markdown('<div class="h-3">Visualization of individual channels:</div>')
|
| 419 |
+
with gr.Accordion("", open=True):
|
| 420 |
+
img_viz = gr.Plot(elem_classes='no-label no-border')
|
| 421 |
+
|
| 422 |
+
choices.change(fn=toggle_file_input, inputs=choices, outputs=[img_path, marker_path])
|
| 423 |
+
|
| 424 |
+
# img_viz = gr.Plot(label="Visualization of individual channels")
|
| 425 |
+
gr.Markdown('<br>')
|
| 426 |
+
gr.Markdown('<div class="h-1">Step 2. Modify Existing Channels</div>')
|
| 427 |
+
gr.Markdown('<div class="h-2">(Required) Define channels designed to visualize nuclei. </div>')
|
| 428 |
+
gr.Markdown('<div class="h-2">(Optional) Remove unwanted channel after visualizing the individual channels. </div>')
|
| 429 |
+
gr.Markdown('<div class="h-2">(Optional) Define channels degisned to visualize membranes.</div><hr>')
|
| 430 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 431 |
with gr.Row(equal_height=True): # third row selects nuclei channels
|
| 432 |
+
with gr.Column(scale=2):
|
|
|
|
| 433 |
selected_nuclei = gr.Dropdown(label='(Required) Select the nuclei channel', interactive=True)
|
| 434 |
+
selected_unwanted_channel = gr.Dropdown(label='(Optional) Select the unwanted channel', interactive=True)
|
| 435 |
selected_membrane = gr.Dropdown(label='(Optional) Select the membrane channel', interactive=True)
|
|
|
|
| 436 |
define_btn = gr.Button('Modify channels')
|
| 437 |
+
with gr.Column(scale=3):
|
| 438 |
+
channel_feedback = gr.Textbox(label='Channels info update')
|
| 439 |
|
| 440 |
# upload the file, and gather channel info. Then populate to the unwanted_channel, nuclei, and membrane components
|
| 441 |
submit_btn.click(
|
|
|
|
| 452 |
# modifies the channels per user input
|
| 453 |
define_btn.click(fn=modify_channels, inputs=[cytof_original_state, selected_unwanted_channel, selected_nuclei, selected_membrane], outputs=[channel_feedback, cytof_state])
|
| 454 |
|
| 455 |
+
gr.Markdown('<br>')
|
| 456 |
+
gr.Markdown('<div class="h-1">Step 3. Perform Cell Segmentation</div>')
|
| 457 |
+
gr.Markdown('<div class="h-2">In this step, we perform cell segmentation based on the defined nuclei and membrane channels</div><hr>')
|
| 458 |
|
| 459 |
with gr.Row(): # This row defines cell radius and performs segmentation
|
| 460 |
+
with gr.Column(scale=2):
|
| 461 |
+
gr.Markdown('<div class="h-2">Cell Size:</div>')
|
| 462 |
+
cell_radius = gr.Number(value=5, precision=0, label='Cell size', info='Please enter the desired radius for cell segmentation (in pixels; default value: 5)', elem_classes='cell-no-label')
|
| 463 |
seg_btn = gr.Button("Segment")
|
| 464 |
+
with gr.Column(scale=3):
|
| 465 |
+
gr.Markdown('<div class="h-2">Visualization of the segmentation: </div>')
|
| 466 |
+
with gr.Accordion("Hover over graph to zoom, pan, save, etc.", open=True):
|
| 467 |
+
seg_viz = gr.Plot(label="Hover over graph to zoom, pan, save, etc.", elem_classes='no-border no-label')
|
| 468 |
seg_btn.click(fn=cell_seg, inputs=[cytof_state, cell_radius], outputs=[seg_viz, cytof_state])
|
| 469 |
+
|
| 470 |
+
gr.Markdown('<br>')
|
| 471 |
+
gr.Markdown('<div class="h-1">Step 4. Extract cell features</div>')
|
| 472 |
+
gr.Markdown('<div class="h-2"><span class="bold">Note</span>: This step will take significantly longer than the previous ones. (A 300MB IMC file takes about 7 minutes to compute.)</div><hr>')
|
| 473 |
|
| 474 |
cohort_state = gr.State(CytofCohort())
|
| 475 |
with gr.Row(): # feature extraction related functinos
|
| 476 |
+
with gr.Column(scale=2):
|
| 477 |
+
# gr.CheckboxGroup(choices=['Yes', 'Yes', 'Yes'], label='')
|
| 478 |
norm_percentile = gr.Slider(minimum=50, maximum=99, step=1, value=75, interactive=True, label='Normalized quantification percentile')
|
| 479 |
extract_btn = gr.Button('Extract')
|
| 480 |
+
with gr.Column(scale=3):
|
| 481 |
+
feat_df = gr.DataFrame(headers=['id','coordinate_x','coordinate_y','area_nuclei'],col_count=(4, "fixed"))
|
| 482 |
|
| 483 |
extract_btn.click(fn=feature_extraction, inputs=[cytof_state, cohort_state, norm_percentile],
|
| 484 |
outputs=[cytof_state, cohort_state, feat_df])
|
| 485 |
|
| 486 |
+
gr.Markdown('<br>')
|
| 487 |
+
gr.Markdown('<div class="h-1">Step 5. Downstream analysis</div><hr>')
|
| 488 |
+
|
| 489 |
+
gr.Markdown('<div class="h-2 bold">(1) Co-expression Analysis</div>')
|
| 490 |
with gr.Row(): # show co-expression and spatial analysis
|
| 491 |
+
with gr.Column(scale=2):
|
| 492 |
+
gr.Markdown('<div class="h-2">This analysis measures the level of co-expression for each pair of biomarkers by calculating the odds ratio between the observed co-occurrence and the expected expressing even</div>')
|
| 493 |
co_exp_btn = gr.Button('Run co-expression analysis')
|
| 494 |
+
with gr.Column(scale=3):
|
| 495 |
+
gr.Markdown('<div class="h-2">Visualization of cell coexpression of markers</div>')
|
| 496 |
+
with gr.Accordion("", open=True):
|
| 497 |
+
co_exp_viz = gr.Plot(elem_classes='no-label no-border')
|
| 498 |
|
| 499 |
+
gr.Markdown('<div class="h-2 bold">(2) Spatial Interactoin Analysis</div>')
|
|
|
|
|
|
|
|
|
|
| 500 |
|
| 501 |
+
def update_info_text(choice):
|
| 502 |
+
if choice == "k-neighbor":
|
| 503 |
+
return 'K-neighbor: classifies the threshold number of surrounding cells as neighborhood pairs.'
|
| 504 |
+
else:
|
| 505 |
+
return 'Distance: classifies cells within threshold distance as neighborhood pairs.'
|
| 506 |
|
| 507 |
+
with gr.Row():
|
| 508 |
+
with gr.Column(scale=2):
|
| 509 |
+
gr.Markdown('<div class="h-2">This analysis measures the degree of co-expression within a pair of neighborhoods.</div>')
|
| 510 |
+
gr.Markdown('<div class="h-2">Select the clustering method:</div>')
|
| 511 |
+
info_text = gr.Markdown(update_info_text('k-neighbor'))
|
| 512 |
+
cluster_method = gr.Radio(['k-neighbor', 'distance'], value='k-neighbor', elem_classes='test', label='')
|
| 513 |
+
cluster_threshold = gr.Slider(minimum=1, maximum=100, step=1, value=30, interactive=True, label='Clustering threshold')
|
| 514 |
+
spatial_btn = gr.Button('Run spatial interaction analysis')
|
| 515 |
+
with gr.Column(scale=3):
|
| 516 |
+
gr.Markdown('<div class="h-2">Visualization of spatial interaction of markers</div>')
|
| 517 |
+
with gr.Accordion("", open=True):
|
| 518 |
+
spatial_viz = gr.Plot(elem_classes='no-label no-border')
|
| 519 |
+
|
| 520 |
+
cluster_method.change(fn=update_info_text, inputs=cluster_method, outputs=info_text)
|
| 521 |
+
co_exp_btn.click(fn=co_expression, inputs=[cytof_state, norm_percentile], outputs=[co_exp_viz, cytof_state])
|
| 522 |
+
# spatial_btn logic is in step6. This is populate the marker positive dropdown options
|
| 523 |
+
|
| 524 |
+
gr.Markdown('<br>')
|
| 525 |
+
gr.Markdown('<div class="h-1">Step 6. Visualize positive markers</div>')
|
| 526 |
+
gr.Markdown('<div class="h-2">Select two markers for side-by-side comparison to visualize their positive states in cells. This serves two purposes: </div>')
|
| 527 |
+
gr.Markdown('<div class="h-2 bold">(1) Validate the co-expression analysis results. (2) Validate teh spatial interaction analysis results.</div>')
|
| 528 |
+
|
| 529 |
|
| 530 |
with gr.Row(): # two marker positive visualization - dropdown options
|
| 531 |
+
with gr.Column(scale=2):
|
| 532 |
+
selected_marker1 = gr.Dropdown(label='Select one marker', info='Select a marker to visualize', interactive=True)
|
| 533 |
+
selected_marker2 = gr.Dropdown(label='Select another marker', info='Selecting the same marker as the previous one is allowed', interactive=True)
|
| 534 |
+
pos_viz_btn = gr.Button('Visualize these two markers')
|
| 535 |
+
with gr.Column(scale=3):
|
| 536 |
+
gr.Markdown('<div class="h-2">Visualization of the two markers.</div>')
|
| 537 |
+
with gr.Accordion("Hover over graph to zoom, pan, save, etc.", open=True):
|
| 538 |
+
marker_pos_viz = gr.Plot(elem_classes='no-label no-border')
|
| 539 |
|
| 540 |
+
spatial_btn.click(
|
| 541 |
+
fn=spatial_interaction, inputs=[cytof_state, norm_percentile, cluster_method, cluster_threshold], outputs=[spatial_viz, cytof_state]
|
| 542 |
+
).success(
|
| 543 |
+
fn=get_marker_pos_options, inputs=[cytof_state], outputs=[selected_marker1, selected_marker2]
|
| 544 |
+
)
|
| 545 |
+
pos_viz_btn.click(fn=viz_pos_marker_pair, inputs=[cytof_state, selected_marker1, selected_marker2, norm_percentile], outputs=[marker_pos_viz])
|
|
|
|
|
|
|
|
|
|
| 546 |
|
| 547 |
+
gr.Markdown('<br>')
|
| 548 |
+
gr.Markdown('<div class="h-1">Step 7. Phenogrpah Clustering</div>')
|
| 549 |
+
gr.Markdown('<div class="h-2">Cells can be clustered into sub-groups based on the extracted single-cell data. (A 300MB IMC file takes about 2 minutes to compute.)</div><hr>')
|
| 550 |
|
| 551 |
with gr.Row(): # add two plots to visualize phenograph results
|
| 552 |
+
with gr.Column(scale=2):
|
| 553 |
+
gr.Markdown('<div class="h-2">We used UMAP to project the high-dimensional data onto a 2-D space.</div>')
|
| 554 |
+
umap_btn = gr.Button('Run Phenograph clustering')
|
| 555 |
+
with gr.Column(scale=3):
|
| 556 |
+
gr.Markdown('<div class="h-2">UMAP Results</div>')
|
| 557 |
+
with gr.Accordion("", open=True):
|
| 558 |
+
phenograph_umap = gr.Plot(elem_classes='no-label no-border')
|
| 559 |
|
| 560 |
+
with gr.Row(): # add two plots to visualize phenograph results
|
| 561 |
+
with gr.Column(scale=2):
|
| 562 |
+
gr.Markdown('<div class="h-2">The previously assigned clusters are also reflected in this figure.</div>')
|
| 563 |
+
cluster_interact_btn = gr.Button('Run clustering interaction')
|
| 564 |
+
with gr.Column(scale=3):
|
| 565 |
+
gr.Markdown('<div class="h-2">Spatial interaction of clusters</div>')
|
| 566 |
+
with gr.Accordion("", open=True):
|
| 567 |
+
cluster_interaction = gr.Plot(elem_classes='no-label no-border')
|
| 568 |
cluster_interact_btn.click(cluster_interaction_fn, inputs=[cytof_state, cohort_state], outputs=[cluster_interaction, cytof_state, cohort_state])
|
| 569 |
|
| 570 |
+
gr.Markdown('<br>')
|
| 571 |
+
gr.Markdown('<div class="h-2">In additional, you could visualizing the cluster assignments against the positive markers to oberve any patterns:</div><hr>')
|
| 572 |
+
|
| 573 |
with gr.Row():
|
| 574 |
+
with gr.Column(scale=2):
|
| 575 |
selected_cluster_marker = gr.Dropdown(label='Select one marker', info='Select a marker to visualize', interactive=True)
|
| 576 |
cluster_positive_btn = gr.Button('Compare clusters and positive markers')
|
| 577 |
+
with gr.Column(scale=3):
|
| 578 |
+
gr.Markdown('<div class="h-2">Cluster assignment vs. positive cells</div>')
|
| 579 |
+
with gr.Accordion("Hover over graph to zoom, pan, save, etc.", open=True):
|
| 580 |
+
cluster_v_positive = gr.Plot(elem_classes='no-label no-border')
|
| 581 |
|
| 582 |
|
| 583 |
umap_btn.click(
|