Skip to content
Snippets Groups Projects

Data explorer with basic viz

Merged fima requested to merge data_explorer into main
1 file
+ 67
46
Compare changes
  • Side-by-side
  • Inline
+ 67
46
@@ -2,12 +2,13 @@ import gradio as gr
@@ -2,12 +2,13 @@ import gradio as gr
import numpy as np
import numpy as np
import os
import os
from qim3d.utils import internal_tools
from qim3d.utils import internal_tools
from qim3d.io import DataLoader
from qim3d.io import load
from qim3d.io.logger import log
from qim3d.io.logger import log
import tifffile
import tifffile
import outputformat as ouf
import outputformat as ouf
import datetime
import datetime
import matplotlib
import matplotlib
 
# matplotlib.use("Agg")
# matplotlib.use("Agg")
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
@@ -31,17 +32,29 @@ class Interface:
@@ -31,17 +32,29 @@ class Interface:
def create_interface(self):
def create_interface(self):
with gr.Blocks(css=self.css_path) as gradio_interface:
with gr.Blocks(css=self.css_path) as gradio_interface:
gr.Markdown("# Data Explorer \n Quick insights from large datasets")
gr.Markdown("# Data Explorer")
with gr.Row():
with gr.Row():
data_path = gr.Textbox(
with gr.Column(scale=0.75):
value="/home/fima/Downloads/MarineGatropod_1.tif",
data_path = gr.Textbox(
max_lines=1,
value="/home/fima/reconstructor-main/small_foram.h5",
label="Path to the 3D volume",
max_lines=1,
 
label="Path to the 3D volume",
 
)
 
with gr.Column(scale=0.25):
 
dataset_name = gr.Textbox(
 
label="Dataset name (in case of H5 files, for example)"
 
)
 
 
with gr.Row(elem_classes="w-256"):
 
cmap = gr.Dropdown(
 
value="viridis",
 
choices=plt.colormaps(),
 
label="Colormap",
 
interactive=True,
)
)
with gr.Row(elem_classes=" w-128"):
with gr.Row(elem_classes="w-128"):
btn_run = gr.Button(value="Load & Run", elem_classes="btn btn-run")
btn_run = gr.Button(value="Load & Run", elem_classes="btn btn-run")
# Outputs
# Outputs
with gr.Row():
with gr.Row():
gr.Markdown("## Data overview")
gr.Markdown("## Data overview")
@@ -85,24 +98,10 @@ class Interface:
@@ -85,24 +98,10 @@ class Interface:
pipeline.verbose = self.verbose
pipeline.verbose = self.verbose
session = gr.State([])
session = gr.State([])
with gr.Row():
gr.Markdown("## Local thickness")
with gr.Row():
gr.Plot()
gr.Plot()
gr.Plot()
with gr.Row():
gr.Markdown("## Structure tensor")
with gr.Row():
gr.Plot()
gr.Plot()
gr.Plot()
### Gradio objects lists
### Gradio objects lists
# Inputs
# Inputs
inputs = [zpos, ypos, xpos]
inputs = [zpos, ypos, xpos, cmap, dataset_name]
# Outputs
# Outputs
outputs = [
outputs = [
data_summary,
data_summary,
@@ -156,6 +155,8 @@ class Interface:
@@ -156,6 +155,8 @@ class Interface:
session.zpos = args[0]
session.zpos = args[0]
session.ypos = args[1]
session.ypos = args[1]
session.xpos = args[2]
session.xpos = args[2]
 
session.cmap = args[3]
 
session.dataset_name = args[4]
return session
return session
@@ -191,7 +192,6 @@ class Interface:
@@ -191,7 +192,6 @@ class Interface:
else:
else:
quiet = True
quiet = True
interface.launch(
interface.launch(
quiet=quiet,
quiet=quiet,
height=self.height,
height=self.height,
@@ -208,6 +208,9 @@ class Session:
@@ -208,6 +208,9 @@ class Session:
self.zpos = 0.5
self.zpos = 0.5
self.ypos = 0.5
self.ypos = 0.5
self.xpos = 0.5
self.xpos = 0.5
 
self.cmap = "viridis"
 
self.dataset_name = None
 
self.error_message = None
# Volume info
# Volume info
self.zsize = None
self.zsize = None
@@ -229,40 +232,51 @@ class Session:
@@ -229,40 +232,51 @@ class Session:
def get_data_info(self):
def get_data_info(self):
# Open file
# Open file
tif = tifffile.TiffFile(self.data_path)
try:
first_slice = tif.pages[0]
vol = load(
 
self.data_path, virtual_stack=True, dataset_name=self.dataset_name
 
)
 
except Exception as error_message:
 
self.error_message = error_message
 
return
 
 
first_slice = vol[0]
# Get info
# Get info
self.zsize = len(tif.pages)
self.zsize = len(vol)
self.ysize, self.xsize = first_slice.shape
self.ysize, self.xsize = first_slice.shape
self.data_type = first_slice.dtype
self.data_type = str(first_slice.dtype)
self.axes = tif.series[0].axes
self.last_modified = datetime.datetime.fromtimestamp(
self.last_modified = datetime.datetime.fromtimestamp(
os.path.getmtime(self.data_path)
os.path.getmtime(self.data_path)
).strftime("%Y-%m-%d %H:%M")
).strftime("%Y-%m-%d %H:%M")
self.file_size = os.path.getsize(self.data_path)
self.file_size = os.path.getsize(self.data_path)
# Close file
tif.close()
def create_summary_dict(self):
def create_summary_dict(self):
# Create dictionary
# Create dictionary
self.summary_dict = {
if self.error_message:
"Last modified": self.last_modified,
self.summary_dict = {"error_mesage": self.error_message}
"File size": internal_tools.sizeof(self.file_size),
"Axes": self.axes,
else:
"Z-size": str(self.zsize),
self.summary_dict = {
"Y-size": str(self.ysize),
"Last modified": self.last_modified,
"X-size": str(self.xsize),
"File size": internal_tools.sizeof(self.file_size),
"Data type": self.data_type,
"Z-size": str(self.zsize),
"Min value": self.min_value,
"Y-size": str(self.ysize),
"Mean value": self.mean_intensity,
"X-size": str(self.xsize),
"Max value": self.max_value,
"Data type": self.data_type,
}
"Min value": self.min_value,
 
"Mean value": self.mean_intensity,
 
"Max value": self.max_value,
 
}
def summary_str(self):
def summary_str(self):
display_dict = {k: v for k, v in self.summary_dict.items() if v is not None}
if "error_mesage" in self.summary_dict:
return ouf.showdict(display_dict, return_str=True, title="Data summary")
error_box = ouf.boxtitle("ERROR", return_str=True)
 
return f"{error_box}\n{self.summary_dict['error_mesage']}"
 
else:
 
display_dict = {k: v for k, v in self.summary_dict.items() if v is not None}
 
return ouf.showdict(display_dict, return_str=True, title="Data summary")
def zslice_from_zpos(self):
def zslice_from_zpos(self):
self.zslice = int(self.zpos * (self.zsize - 1))
self.zslice = int(self.zpos * (self.zsize - 1))
@@ -295,7 +309,13 @@ class Pipeline:
@@ -295,7 +309,13 @@ class Pipeline:
session.create_summary_dict()
session.create_summary_dict()
# Memory map data as a virtual stack
# Memory map data as a virtual stack
session.vol = DataLoader().load_tiff(session.data_path)
 
try:
 
session.vol = load(
 
session.data_path, virtual_stack=True, dataset_name=session.dataset_name
 
)
 
except:
 
return session
if self.verbose:
if self.verbose:
log.info(ouf.br(3, return_str=True) + session.summary_str())
log.info(ouf.br(3, return_str=True) + session.summary_str())
@@ -324,6 +344,7 @@ class Pipeline:
@@ -324,6 +344,7 @@ class Pipeline:
def create_slice_fig(self, axis, session):
def create_slice_fig(self, axis, session):
plt.close()
plt.close()
vol = session.vol
vol = session.vol
 
plt.set_cmap(session.cmap)
zslice = session.zslice_from_zpos()
zslice = session.zslice_from_zpos()
yslice = session.yslice_from_ypos()
yslice = session.yslice_from_ypos()
Loading