Skip to content
Snippets Groups Projects
Commit 912e9724 authored by David Grundfest's avatar David Grundfest
Browse files

Updated gradio interface

Now it uses our base classes and is way shorter. Got rid of more than
200 lines of code. I opened an issue https://github.com/gradio-app/gradio/issues/9273
regarding interrupting chain of events.
Deleted or moved some files like notebooks, which shouldnt be part of the package.
parent 99b5ff54
No related branches found
No related tags found
2 merge requests!117New Layered Surface Segmentation,!42Layered Surface Segmentation Feature
...@@ -32,6 +32,9 @@ def main(): ...@@ -32,6 +32,9 @@ def main():
gui_parser.add_argument( gui_parser.add_argument(
"--local-thickness", action="store_true", help="Run local thickness tool." "--local-thickness", action="store_true", help="Run local thickness tool."
) )
gui_parser.add_argument(
"--layers", action="store_true", help="Run Layers."
)
gui_parser.add_argument("--host", default="0.0.0.0", help="Desired host.") gui_parser.add_argument("--host", default="0.0.0.0", help="Desired host.")
gui_parser.add_argument( gui_parser.add_argument(
"--platform", action="store_true", help="Use QIM platform address" "--platform", action="store_true", help="Use QIM platform address"
...@@ -127,6 +130,8 @@ def main(): ...@@ -127,6 +130,8 @@ def main():
interface_class = qim3d.gui.annotation_tool.Interface interface_class = qim3d.gui.annotation_tool.Interface
elif args.local_thickness: elif args.local_thickness:
interface_class = qim3d.gui.local_thickness.Interface interface_class = qim3d.gui.local_thickness.Interface
elif args.layers:
interface_class = qim3d.gui.layers2d.Interface
else: else:
print( print(
"Please select a tool by choosing one of the following flags:\n\t--data-explorer\n\t--iso3d\n\t--annotation-tool\n\t--local-thickness" "Please select a tool by choosing one of the following flags:\n\t--data-explorer\n\t--iso3d\n\t--annotation-tool\n\t--local-thickness"
......
...@@ -4,6 +4,7 @@ from . import data_explorer ...@@ -4,6 +4,7 @@ from . import data_explorer
from . import iso3d from . import iso3d
from . import local_thickness from . import local_thickness
from . import annotation_tool from . import annotation_tool
from . import layers2d
from .qim_theme import QimTheme from .qim_theme import QimTheme
......
import os import os
import gradio as gr
from qim3d.utils import internal_tools
from qim3d.io import DataLoader
from qim3d.io.logger import log
from qim3d.process import layers2d as l2d
from qim3d.io import load
import qim3d.viz
# matplotlib.use("Agg") import gradio as gr
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from .interface import BaseInterface
class Session: from qim3d.processing import layers2d as l2d
def __init__(self): from qim3d.io import load
self.data = None import qim3d.viz
self.virtual_stack = True
self.dataset_name = ""
self.base_path = None
self.explorer = None
self.file_path = None
# Layers2D objects
self.l2d_obj_x = None
self.l2d_obj_y = None
self.l2d_obj_z = None
# Layers2D parameters
self.delta = 0
self.min_margin = 0
self.n_layers = 0
self.is_inverted = False
# Axis positions
self.x_pos = 0
self.y_pos = 0
self.z_pos = 0
# Slices
self.x_slice = None
self.y_slice = None
self.z_slice = None
class Interface:
def __init__(self):
self.title = "Layered surfaces 2D"
# Data examples
current_dir = os.path.dirname(os.path.abspath(__file__))
# examples_dir = ["..", "img_examples"]
# examples = [
# "blobs_256x256x256.tif",
# "cement_128x128x128.tif",
# "bone_128x128x128.tif",
# "slice_218x193.png",
# ]
# self.img_examples = []
# for example in examples:
# self.img_examples.append(
# [os.path.join(current_dir, *examples_dir, example)]
# )
# CSS path
self.css_path = os.path.join(current_dir, "..", "css", "gradio.css")
def start_session(self, *args):
session = Session()
session.base_path = args[0]
session.explorer = args[1]
session.delta = args[2]
session.min_margin = args[3]
session.n_layers = args[4]
session.is_inverted = args[5]
session.x_pos = args[6]
session.y_pos = args[7]
session.z_pos = args[8]
# Get the file path from the explorer or base path
if session.base_path and os.path.isfile(session.base_path):
session.file_path = session.base_path
elif session.explorer and os.path.isfile(session.explorer):
session.file_path = session.explorer
else:
raise ValueError("Invalid file path")
return session
def update_session_x_pos(self, session, x_pos):
session.x_pos = x_pos
return session
def update_session_y_pos(self, session, y_pos):
session.y_pos = y_pos
return session
def update_session_z_pos(self, session, z_pos):
session.z_pos = z_pos
return session
def update_session_delta(self, session, delta):
session.delta = delta
return session
def update_session_min_margin(self, session, min_margin): #TODO figure out how not update anything and go through processing when there are no data loaded
session.min_margin = min_margin # So user could play with the widgets but it doesnt throw error
return session # Right now its only bypassed with several if statements
# I opened an issue here https://github.com/gradio-app/gradio/issues/9273
def update_session_n_layers(self, session, n_layers): class Interface(BaseInterface):
session.n_layers = n_layers def __init__(self):
return session super().__init__("Layered surfaces 2D", 1080)
def update_session_is_inverted(self, session, is_inverted): self.l2d_obj_x = l2d.Layers2d()
session.is_inverted = is_inverted self.l2d_obj_y = l2d.Layers2d()
return session self.l2d_obj_z = l2d.Layers2d()
def update_explorer(self, new_path): self.figsize = (8, 8)
# Refresh the file explorer object self.cmap = "Greys_r"
new_path = os.path.expanduser(new_path)
# In case we have a directory self.data = None
if os.path.isdir(new_path):
return gr.update(root=new_path, label=new_path)
elif os.path.isfile(new_path): self.virtual_stack = True #TODO ask why
parent_dir = os.path.dirname(new_path) self.dataset_name = '' #TODO check if necessary to even have
file_name = str(os.path.basename(new_path))
return gr.update(root=parent_dir, label=parent_dir, value=file_name)
else: self.error_state = False
raise ValueError("Invalid path")
def set_relaunch_button(self):
# Sets the button to relaunch
return gr.update(
elem_classes="btn btn-run",
value=f"Relaunch",
interactive=True,
)
def set_spinner(self, message):
# spinner icon/shows the user something is happeing
return gr.update(
elem_classes="btn btn-spinner",
value=f"{message}",
interactive=False,
)
def create_interface(self):
with gr.Blocks(css=self.css_path) as gradio_interface:
gr.Markdown(f"# {self.title}")
def define_interface(self):
with gr.Row(): with gr.Row():
# Control panel: Input data and parameters
with gr.Column(scale=1, min_width=320): with gr.Column(scale=1, min_width=320):
with gr.Row(): with gr.Row():
with gr.Column(scale=99, min_width=128): with gr.Column(scale=99, min_width=128):
...@@ -159,21 +43,20 @@ class Interface: ...@@ -159,21 +43,20 @@ class Interface:
max_lines=1, max_lines=1,
container=False, container=False,
label="Base path", label="Base path",
elem_classes="h-36",
value=os.getcwd(), value=os.getcwd(),
) )
with gr.Column(scale=1, min_width=36): with gr.Column(scale=1, min_width=36):
reload_base_path = gr.Button( reload_base_path = gr.Button(value="")
value="", elem_classes="btn-html h-36"
)
explorer = gr.FileExplorer( explorer = gr.FileExplorer(
glob="{*/,}{*.*}", ignore_glob="*/.*",
root=os.getcwd(), root_dir=os.getcwd(),
label=os.getcwd(), label=os.getcwd(),
render=True, render=True,
file_count="single", file_count="single",
interactive=True, interactive=True,
elem_classes="h-256 hide-overflow", height = 230,
) )
# Parameters sliders and checkboxes # Parameters sliders and checkboxes
...@@ -184,7 +67,7 @@ class Interface: ...@@ -184,7 +67,7 @@ class Interface:
value=0.75, value=0.75,
step=0.01, step=0.01,
label="Delta value", label="Delta value",
info="Delta value for the gradient calculation. The lower the delta value is set, the more accurate the gradient calculation will be. However, the calculation takes longer to execute.", info="The lower the delta is, the more accurate the gradient calculation will be. However, the calculation takes longer to execute.",
) )
with gr.Row(): with gr.Row():
...@@ -213,11 +96,8 @@ class Interface: ...@@ -213,11 +96,8 @@ class Interface:
info="To invert the image before processing, click this box. By inverting the source image before processing, the algorithm effectively flips the gradient.", info="To invert the image before processing, click this box. By inverting the source image before processing, the algorithm effectively flips the gradient.",
) )
# Relaunch button
with gr.Row(): with gr.Row():
btn_run = gr.Button( btn_run = gr.Button("Run Layers2D", variant = 'primary')
"Run Layers2D", elem_classes="btn btn-html btn-run"
)
# Output panel: Plots # Output panel: Plots
with gr.Column(scale=2): with gr.Column(scale=2):
...@@ -226,39 +106,36 @@ class Interface: ...@@ -226,39 +106,36 @@ class Interface:
show_label=True, show_label=True,
label="Slice along X-axis", label="Slice along X-axis",
visible=True, visible=True,
elem_classes="rounded",
) )
input_plot_y = gr.Plot( input_plot_y = gr.Plot(
show_label=True, show_label=True,
label="Slice along Y-axis", label="Slice along Y-axis",
visible=True, visible=True,
elem_classes="rounded",
) )
input_plot_z = gr.Plot( input_plot_z = gr.Plot(
show_label=True, show_label=True,
label="Slice along Z-axis", label="Slice along Z-axis",
visible=True, visible=True,
elem_classes="rounded",
) )
with gr.Row(): # Detected layers outputs with gr.Row(): # Detected layers outputs
output_plot_x = gr.Plot( output_plot_x = gr.Plot(
show_label=True, show_label=True,
label="Detected layers X-axis", label="Detected layers X-axis",
visible=True, visible=True,
elem_classes="rounded",
) )
output_plot_y = gr.Plot( output_plot_y = gr.Plot(
show_label=True, show_label=True,
label="Detected layers Y-axis", label="Detected layers Y-axis",
visible=True, visible=True,
elem_classes="rounded",
) )
output_plot_z = gr.Plot( output_plot_z = gr.Plot(
show_label=True, show_label=True,
label="Detected layers Z-axis", label="Detected layers Z-axis",
visible=True, visible=True,
elem_classes="rounded",
) )
with gr.Row(): # Axis position sliders with gr.Row(): # Axis position sliders
x_pos = gr.Slider( x_pos = gr.Slider(
minimum=0, minimum=0,
...@@ -285,11 +162,11 @@ class Interface: ...@@ -285,11 +162,11 @@ class Interface:
info="The 3D image is sliced along the Z-axis.", info="The 3D image is sliced along the Z-axis.",
) )
session = gr.State([]) positions = [x_pos, y_pos, z_pos]
process_inputs = [is_inverted, delta, min_margin, n_layers]
pipeline = Pipeline() input_plots = [input_plot_x, input_plot_y, input_plot_z]
output_plots = [output_plot_x, output_plot_y, output_plot_z]
inputs = [base_path, explorer, delta, min_margin, n_layers, is_inverted, x_pos, y_pos, z_pos]
spinner_loading = gr.Text("Loading data...", visible=False) spinner_loading = gr.Text("Loading data...", visible=False)
spinner_running = gr.Text("Running pipeline...", visible=False) spinner_running = gr.Text("Running pipeline...", visible=False)
spinner_updating = gr.Text("Updating layers...", visible=False) spinner_updating = gr.Text("Updating layers...", visible=False)
...@@ -299,214 +176,129 @@ class Interface: ...@@ -299,214 +176,129 @@ class Interface:
fn=self.update_explorer,inputs=base_path, outputs=explorer) fn=self.update_explorer,inputs=base_path, outputs=explorer)
btn_run.click( btn_run.click(
fn=self.start_session, inputs=inputs, outputs=session).then(
fn=self.set_spinner, inputs=spinner_loading, outputs=btn_run).then( fn=self.set_spinner, inputs=spinner_loading, outputs=btn_run).then(
fn=pipeline.load_data, inputs=session, outputs=session).then( fn=self.load_data, inputs = [base_path, explorer]).then(
fn=self.set_spinner, inputs=spinner_running, outputs=btn_run).then( fn=self.set_spinner, inputs=spinner_running, outputs=btn_run).then(
fn=pipeline.update_slices, inputs=session, outputs=session).then( fn=self.process_all, inputs = [*positions, *process_inputs]).then(
fn=pipeline.process_l2d_x, inputs=session, outputs=session).then( fn=self.plot_input_img_all, inputs = positions, outputs = input_plots, show_progress='hidden').then(
fn=pipeline.process_l2d_y, inputs=session, outputs=session).then( fn=self.plot_output_all, outputs = output_plots, show_progress='hidden').then(
fn=pipeline.process_l2d_z, inputs=session, outputs=session).then(
fn=pipeline.plot_input_img_x, inputs=session, outputs=input_plot_x).then(
fn=pipeline.plot_input_img_y, inputs=session, outputs=input_plot_y).then(
fn=pipeline.plot_input_img_z, inputs=session, outputs=input_plot_z).then(
fn=pipeline.plot_l2d_output_x, inputs=session, outputs=output_plot_x).then(
fn=pipeline.plot_l2d_output_y, inputs=session, outputs=output_plot_y).then(
fn=pipeline.plot_l2d_output_z, inputs=session, outputs=output_plot_z).then(
fn=self.set_relaunch_button, inputs=[], outputs=btn_run) fn=self.set_relaunch_button, inputs=[], outputs=btn_run)
delta.change( gr.on(
fn=self.update_session_delta, inputs=[session, delta], outputs=session, show_progress=False).success( triggers=[delta.change, min_margin.change, n_layers.change, is_inverted.change],
fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then( fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then(
fn=pipeline.update_slices, inputs=session, outputs=session).then( fn=self.process_all, inputs = [*positions, *process_inputs]).then(
fn=pipeline.process_l2d_x, inputs=session, outputs=session).then( fn=self.plot_output_all, outputs = output_plots, show_progress='hidden').then(
fn=pipeline.process_l2d_y, inputs=session, outputs=session).then(
fn=pipeline.process_l2d_z, inputs=session, outputs=session).then(
fn=pipeline.plot_l2d_output_x, inputs=session, outputs=output_plot_x).then(
fn=pipeline.plot_l2d_output_y, inputs=session, outputs=output_plot_y).then(
fn=pipeline.plot_l2d_output_z, inputs=session, outputs=output_plot_z).then(
fn=self.set_relaunch_button, inputs=[], outputs=btn_run) fn=self.set_relaunch_button, inputs=[], outputs=btn_run)
min_margin.change( slider_change_arguments = (
fn=self.update_session_min_margin, inputs=[session, min_margin], outputs=session, show_progress=False).success( (x_pos, self.process_x, self.plot_input_img_x, input_plot_x, self.l2d_obj_x, output_plot_x),
fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then( (y_pos, self.process_y, self.plot_input_img_y, input_plot_y, self.l2d_obj_y, output_plot_y),
fn=pipeline.update_slices, inputs=session, outputs=session).then( (z_pos, self.process_z, self.plot_input_img_z, input_plot_z, self.l2d_obj_z, output_plot_z))
fn=pipeline.process_l2d_x, inputs=session, outputs=session).then(
fn=pipeline.process_l2d_y, inputs=session, outputs=session).then(
fn=pipeline.process_l2d_z, inputs=session, outputs=session).then(
fn=pipeline.plot_l2d_output_x, inputs=session, outputs=output_plot_x).then(
fn=pipeline.plot_l2d_output_y, inputs=session, outputs=output_plot_y).then(
fn=pipeline.plot_l2d_output_z, inputs=session, outputs=output_plot_z).then(
fn=self.set_relaunch_button, inputs=[], outputs=btn_run)
n_layers.change( for slider, process_func, plot_input_func, input_plot, l2d_obj, output_plot in slider_change_arguments:
fn=self.update_session_n_layers, inputs=[session, n_layers], outputs=session, show_progress=False).success( slider.change(
fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then( fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then(
fn=pipeline.update_slices, inputs=session, outputs=session).then( fn=process_func, inputs=[slider, *process_inputs]).then(
fn=pipeline.process_l2d_x, inputs=session, outputs=session).then( fn=plot_input_func, inputs=slider, outputs=input_plot, show_progress='hidden').then(
fn=pipeline.process_l2d_y, inputs=session, outputs=session).then( fn=self.plot_output_wrapper(l2d_obj), outputs=output_plot, show_progress='hidden').then(
fn=pipeline.process_l2d_z, inputs=session, outputs=session).then(
fn=pipeline.plot_l2d_output_x, inputs=session, outputs=output_plot_x).then(
fn=pipeline.plot_l2d_output_y, inputs=session, outputs=output_plot_y).then(
fn=pipeline.plot_l2d_output_z, inputs=session, outputs=output_plot_z).then(
fn=self.set_relaunch_button, inputs=[], outputs=btn_run) fn=self.set_relaunch_button, inputs=[], outputs=btn_run)
is_inverted.change(
fn=self.update_session_is_inverted, inputs=[session, is_inverted], outputs=session, show_progress=False).success(
fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then(
fn=pipeline.update_slices, inputs=session, outputs=session).then(
fn=pipeline.process_l2d_x, inputs=session, outputs=session).then(
fn=pipeline.process_l2d_y, inputs=session, outputs=session).then(
fn=pipeline.process_l2d_z, inputs=session, outputs=session).then(
fn=pipeline.plot_l2d_output_x, inputs=session, outputs=output_plot_x).then(
fn=pipeline.plot_l2d_output_y, inputs=session, outputs=output_plot_y).then(
fn=pipeline.plot_l2d_output_z, inputs=session, outputs=output_plot_z).then(
fn=self.set_relaunch_button, inputs=[], outputs=btn_run)
x_pos.change( def update_explorer(self, new_path):
fn=self.update_session_x_pos, inputs=[session, x_pos], outputs=session, show_progress=False).success( # Refresh the file explorer object
fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then( new_path = os.path.expanduser(new_path)
fn=pipeline.update_slices, inputs=session, outputs=session).then(
fn=pipeline.process_l2d_x, inputs=session, outputs=session).then(
fn=pipeline.plot_input_img_x, inputs=session, outputs=input_plot_x).then(
fn=pipeline.plot_l2d_output_x, inputs=session, outputs=output_plot_x).then(
fn=self.set_relaunch_button, inputs=[], outputs=btn_run)
y_pos.change( # In case we have a directory
fn=self.update_session_y_pos, inputs=[session, y_pos], outputs=session, show_progress=False).success( if os.path.isdir(new_path):
fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then( return gr.update(root_dir=new_path, label=new_path)
fn=pipeline.update_slices, inputs=session, outputs=session).then(
fn=pipeline.process_l2d_y, inputs=session, outputs=session).then(
fn=pipeline.plot_input_img_y, inputs=session, outputs=input_plot_y).then(
fn=pipeline.plot_l2d_output_y, inputs=session, outputs=output_plot_y).then(
fn=self.set_relaunch_button, inputs=[], outputs=btn_run)
z_pos.change( elif os.path.isfile(new_path):
fn=self.update_session_z_pos, inputs=[session, z_pos], outputs=session, show_progress=False).success( parent_dir = os.path.dirname(new_path)
fn=self.set_spinner, inputs=spinner_updating, outputs=btn_run).then( file_name = str(os.path.basename(new_path))
fn=pipeline.update_slices, inputs=session, outputs=session).then( return gr.update(root_dir=parent_dir, label=parent_dir, value=file_name)
fn=pipeline.process_l2d_z, inputs=session, outputs=session).then(
fn=pipeline.plot_input_img_z, inputs=session, outputs=input_plot_z).then(
fn=pipeline.plot_l2d_output_z, inputs=session, outputs=output_plot_z).then(
fn=self.set_relaunch_button, inputs=[], outputs=btn_run)
# fmt: on else:
raise ValueError("Invalid path")
return gradio_interface def set_relaunch_button(self):
# Sets the button to relaunch
return gr.update(
value=f"Relaunch",
interactive=True,
)
def set_spinner(self, message):
if not self.error_state:
return gr.Button()
# spinner icon/shows the user something is happeing
return gr.update(
value=f"{message}",
interactive=False,
)
class Pipeline: def load_data(self, base_path, explorer):
def __init__(self): if base_path and os.path.isfile(base_path):
self.figsize = (8, 8) file_path = base_path
elif explorer and os.path.isfile(explorer):
file_path = explorer
else:
raise gr.Error("Invalid file path")
def load_data(self, session):
try: try:
session.data = load( self.data = load(
session.file_path, file_path,
virtual_stack=session.virtual_stack, virtual_stack=self.virtual_stack,
dataset_name=session.dataset_name, dataset_name=self.dataset_name,
) )
except Exception as error_message: except Exception as error_message:
raise ValueError( raise gr.Error(
f"Failed to load the image: {error_message}" f"Failed to load the image: {error_message}"
) from error_message ) from error_message
return session def idx(self, pos, axis):
return int(pos * (self.data.shape[axis] - 1))
def update_slices(self, session):
x_idx = int(session.x_pos * (session.data.shape[0] - 1))
y_idx = int(session.y_pos * (session.data.shape[1] - 1))
z_idx = int(session.z_pos * (session.data.shape[2] - 1))
session.x_slice = session.data[x_idx, :, :] # PROCESSING FUNCTIONS
session.y_slice = session.data[:, y_idx, :]
session.z_slice = session.data[:, :, z_idx]
return session
def process_l2d_x(self, session):
if session.l2d_obj_x is None:
l2d_obj = l2d.Layers2d()
else:
l2d_obj = session.l2d_obj_x
def process(self, l2d_obj:l2d.Layers2d, slice, is_inverted, delta, min_margin, n_layers):
l2d_obj.prepare_update( l2d_obj.prepare_update(
data=session.x_slice, data = slice,
is_inverted=session.is_inverted, is_inverted = is_inverted,
delta=session.delta, delta = delta,
min_margin=session.min_margin, min_margin = min_margin,
n_layers=session.n_layers, n_layers = n_layers,
) )
l2d_obj.update() l2d_obj.update()
session.l2d_obj_x = l2d_obj def process_x(self, x_pos, is_inverted, delta, min_margin, n_layers):
if self.data is not None:
return session slice = self.data[self.idx(x_pos, 0), :, :]
self.process(self.l2d_obj_x, slice, is_inverted, delta, min_margin, n_layers)
def process_l2d_y(self, session):
if session.l2d_obj_y is None:
l2d_obj = l2d.Layers2d()
else:
l2d_obj = session.l2d_obj_y
l2d_obj.prepare_update(
data=session.y_slice,
is_inverted=session.is_inverted,
delta=session.delta,
min_margin=session.min_margin,
n_layers=session.n_layers,
)
l2d_obj.update()
session.l2d_obj_y = l2d_obj
return session
def process_l2d_z(self, session):
if session.l2d_obj_z is None:
l2d_obj = l2d.Layers2d()
else:
l2d_obj = session.l2d_obj_z
l2d_obj.prepare_update(
data=session.z_slice,
is_inverted=session.is_inverted,
delta=session.delta,
min_margin=session.min_margin,
n_layers=session.n_layers,
)
l2d_obj.update()
session.l2d_obj_z = l2d_obj
return session
# Plotting functions
def plot_input_img_x(self, session, cmap="Greys_r"):
plt.close()
fig, ax = plt.subplots(figsize=self.figsize)
ax.imshow(session.x_slice, interpolation="nearest", cmap=cmap)
# Adjustments def process_y(self, y_pos, is_inverted, delta, min_margin, n_layers):
ax.axis("off") if self.data is not None:
fig.subplots_adjust(left=0, right=1, bottom=0, top=1) slice = self.data[:, self.idx(y_pos, 1), :]
self.process(self.l2d_obj_y, slice, is_inverted, delta, min_margin, n_layers)
return fig def process_z(self, z_pos, is_inverted, delta, min_margin, n_layers):
if self.data is not None:
slice = self.data[:, :, self.idx(z_pos, 2)]
self.process(self.l2d_obj_z, slice, is_inverted, delta, min_margin, n_layers)
def plot_input_img_y(self, session, cmap="Greys_r"): def process_all(self, x_pos, y_pos, z_pos, is_inverted, delta, min_margin, n_layers):
plt.close() self.process_x(x_pos, is_inverted, delta, min_margin, n_layers)
fig, ax = plt.subplots(figsize=self.figsize) self.process_y(y_pos, is_inverted, delta, min_margin, n_layers)
ax.imshow(session.y_slice, interpolation="nearest", cmap=cmap) self.process_z(z_pos, is_inverted, delta, min_margin, n_layers)
# Adjustments
ax.axis("off")
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
return fig # PLOTTING FUNCTIONS
def plot_input_img_z(self, session, cmap="Greys_r"): def plot_input_img(self, slice):
plt.close() plt.close()
fig, ax = plt.subplots(figsize=self.figsize) fig, ax = plt.subplots(figsize=self.figsize)
ax.imshow(session.z_slice, interpolation="nearest", cmap=cmap) ax.imshow(slice, interpolation="nearest", cmap = self.cmap)
# Adjustments # Adjustments
ax.axis("off") ax.axis("off")
...@@ -514,65 +306,51 @@ class Pipeline: ...@@ -514,65 +306,51 @@ class Pipeline:
return fig return fig
def plot_l2d_output_x(self, session): def plot_input_img_x(self, x_pos):
l2d_obj = session.l2d_obj_x if self.data is None:
return gr.Plot()
slice = self.data[self.idx(x_pos, 0), :, :]
return self.plot_input_img(slice)
def plot_input_img_y(self, y_pos):
if self.data is None:
return gr.Plot()
slice = self.data[:, self.idx(y_pos, 1), :]
return self.plot_input_img(slice)
def plot_input_img_z(self, z_pos):
if self.data is None:
return gr.Plot()
slice = self.data[:, :, self.idx(z_pos, 2)]
return self.plot_input_img(slice)
def plot_input_img_all(self, x_pos, y_pos, z_pos):
x_plot = self.plot_input_img_x(x_pos)
y_plot = self.plot_input_img_y(y_pos)
z_plot = self.plot_input_img_z(z_pos)
return x_plot, y_plot, z_plot
def plot_output_wrapper(self, l2d_obj:l2d.Layers2d):
def plot_l2d_output():
if self.data is None:
return gr.Plot()
fig, ax = qim3d.viz.layers2d.create_plot_of_2d_array(l2d_obj.get_data_not_inverted()) fig, ax = qim3d.viz.layers2d.create_plot_of_2d_array(l2d_obj.get_data_not_inverted())
data_lines = [] for line in l2d_obj.segmentation_lines:
for i in range(len(l2d_obj.get_segmentation_lines())):
data_lines.append(l2d_obj.get_segmentation_lines()[i])
# Show how add_line_to_plot works:
for line in data_lines:
qim3d.viz.layers2d.add_line_to_plot(ax, line) qim3d.viz.layers2d.add_line_to_plot(ax, line)
# Adjustments
ax.axis("off")
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
return fig
def plot_l2d_output_y(self, session):
l2d_obj = session.l2d_obj_y
fig, ax = qim3d.viz.layers2d.create_plot_of_2d_array(l2d_obj.get_data_not_inverted())
data_lines = []
for i in range(len(l2d_obj.get_segmentation_lines())):
data_lines.append(l2d_obj.get_segmentation_lines()[i])
# Show how add_line_to_plot works:
for line in data_lines:
qim3d.viz.layers2d.add_line_to_plot(ax, line)
# Adjustments
ax.axis("off")
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
return fig
def plot_l2d_output_z(self, session):
l2d_obj = session.l2d_obj_z
fig, ax = qim3d.viz.layers2d.create_plot_of_2d_array(l2d_obj.get_data_not_inverted())
data_lines = []
for i in range(len(l2d_obj.get_segmentation_lines())):
data_lines.append(l2d_obj.get_segmentation_lines()[i])
# Show how add_line_to_plot works:
for line in data_lines:
qim3d.viz.layers2d.add_line_to_plot(ax, line)
# Adjustments
ax.axis("off") ax.axis("off")
fig.subplots_adjust(left=0, right=1, bottom=0, top=1) fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
return fig return fig
return plot_l2d_output
def run_interface(host = "0.0.0.0"): def plot_output_all(self):
gradio_interface = Interface().create_interface() x_output = self.plot_output_wrapper(self.l2d_obj_x)()
internal_tools.run_gradio_app(gradio_interface,host) y_output = self.plot_output_wrapper(self.l2d_obj_y)()
z_output = self.plot_output_wrapper(self.l2d_obj_z)()
return x_output, y_output, z_output
if __name__ == "__main__": if __name__ == "__main__":
# Creates interface Interface().run_interface()
run_interface()
\ No newline at end of file
from .layers2d import Layers2d
\ No newline at end of file
File moved
Source diff could not be displayed: it is too large. Options to address this: view the blob.
from . import colormaps
from .cc import plot_cc
from .detection import circles
from .explore import (
interactive_fade_mask,
orthogonal,
slicer,
slices,
)
from .k3d import vol
from .local_thickness_ import local_thickness
from .structure_tensor import vectors
from .metrics import plot_metrics, grid_overview, grid_pred, vol_masked
from .preview import image_preview
from . import layers2d
\ No newline at end of file
""" Provides a collection of visualisation functions for the Layers2d class.""" """ Provides a collection of visualisation functions for the Layers2d class."""
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
from qim3d.process import layers2d as l2d from qim3d.processing import layers2d as l2d
def create_subplot_of_2d_arrays(data, m_rows = 1, n_cols = 1, figsize = None): def create_subplot_of_2d_arrays(data, m_rows = 1, n_cols = 1, figsize = None):
''' '''
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment