feat: Enhance volumetric data parsing by adding progress updates and refactoring worker processes
This commit is contained in:
@@ -13,7 +13,7 @@ import SimpleITK as sitk
|
|||||||
from ..props import BIOXEL_Series
|
from ..props import BIOXEL_Series
|
||||||
from ..utils import get_layer_obj, wrapped_label
|
from ..utils import get_layer_obj, wrapped_label
|
||||||
|
|
||||||
from ..bioxel.parse import DICOM_EXTS, SUPPORT_EXTS, get_ext
|
from ..bioxel.parse import DICOM_EXTS, SUPPORT_EXTS, get_ext, parse_volumetric_data
|
||||||
|
|
||||||
from ..utils import get_cache_dir, progress_update, progress_bar
|
from ..utils import get_cache_dir, progress_update, progress_bar
|
||||||
from ..layer import get_layer_caches, set_layer_caches
|
from ..layer import get_layer_caches, set_layer_caches
|
||||||
@@ -87,7 +87,10 @@ def start_worker_process(owner, command: str, payload: dict):
|
|||||||
"cancel_path": str(cancel_path),
|
"cancel_path": str(cancel_path),
|
||||||
}
|
}
|
||||||
write_worker_json(config_path, config)
|
write_worker_json(config_path, config)
|
||||||
write_worker_json(progress_path, {"factor": 0.0, "text": "Starting..."})
|
write_worker_json(
|
||||||
|
progress_path,
|
||||||
|
{"factor": 0.0, "text": "Starting background Blender..."},
|
||||||
|
)
|
||||||
|
|
||||||
print(f"Starting Bioxel worker with addon module: {addon_name}")
|
print(f"Starting Bioxel worker with addon module: {addon_name}")
|
||||||
cmd = [
|
cmd = [
|
||||||
@@ -198,7 +201,6 @@ class ImportDataBase:
|
|||||||
context.window_manager.fileselect_add(self)
|
context.window_manager.fileselect_add(self)
|
||||||
return {"RUNNING_MODAL"}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
|
|
||||||
class ImportData(bpy.types.Operator, ImportDataBase):
|
class ImportData(bpy.types.Operator, ImportDataBase):
|
||||||
bl_idname = "bioxel.import_data"
|
bl_idname = "bioxel.import_data"
|
||||||
bl_label = "Import Data"
|
bl_label = "Import Data"
|
||||||
@@ -301,64 +303,26 @@ class ParseVolumetricData(bpy.types.Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
print("Collecting Meta Data...")
|
print("Collecting Meta Data...")
|
||||||
self.is_cancelled = False
|
progress_update(context, 0.0, "Collecting Meta Data...")
|
||||||
self.has_error = None
|
|
||||||
self.meta = None
|
|
||||||
self.label_count = 0
|
|
||||||
self.dtype = None
|
|
||||||
|
|
||||||
start_worker_process(
|
def progress_callback(factor, text):
|
||||||
self,
|
progress_update(context, factor, text)
|
||||||
"read_meta",
|
|
||||||
{
|
|
||||||
"filepath": self.filepath,
|
|
||||||
"series_id": self.series_id,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
self._timer = context.window_manager.event_timer_add(
|
try:
|
||||||
time_step=0.1, window=context.window
|
series_id = self.series_id if self.series_id != "empty" else ""
|
||||||
)
|
data, meta = parse_volumetric_data(
|
||||||
bpy.types.STATUSBAR_HT_header.append(progress_bar)
|
data_file=self.filepath,
|
||||||
context.window_manager.modal_handler_add(self)
|
series_id=series_id,
|
||||||
return {"RUNNING_MODAL"}
|
progress_callback=progress_callback,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
|
||||||
def modal(self, context, event):
|
self.meta = meta
|
||||||
if event.type == "ESC":
|
self.label_count = int(np.max(data))
|
||||||
cancel_worker_process(self, context)
|
self.dtype = data.dtype
|
||||||
return {"PASS_THROUGH"}
|
|
||||||
|
|
||||||
if event.type != "TIMER":
|
|
||||||
return {"PASS_THROUGH"}
|
|
||||||
|
|
||||||
bpy.context.workspace.status_text_set_internal(None)
|
|
||||||
update_worker_progress(self, context)
|
|
||||||
|
|
||||||
if self.process.poll() is None:
|
|
||||||
return {"PASS_THROUGH"}
|
|
||||||
|
|
||||||
context.window_manager.event_timer_remove(self._timer)
|
|
||||||
remove_progress_bar_safe()
|
|
||||||
progress_update(context, 1.0)
|
progress_update(context, 1.0)
|
||||||
|
|
||||||
result = read_worker_json(self.result_path)
|
|
||||||
if self.is_cancelled or (result and result.get("cancelled")):
|
|
||||||
self.report({"WARNING"}, "Canncelled by user.")
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
if not result:
|
|
||||||
self.report({"ERROR"}, f"Import worker failed. See log: {self.log_path}")
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
if not result.get("ok"):
|
|
||||||
print(result.get("traceback", ""))
|
|
||||||
self.report({"ERROR"}, result.get("error", "Import worker failed."))
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
self.meta = result["meta"]
|
|
||||||
self.label_count = int(result["label_count"])
|
|
||||||
self.dtype = np.dtype(result["dtype"])
|
|
||||||
|
|
||||||
for key, value in self.meta.items():
|
for key, value in self.meta.items():
|
||||||
print(f"{key}: {value}")
|
print(f"{key}: {value}")
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,6 @@ import json
|
|||||||
import traceback
|
import traceback
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import transforms3d
|
|
||||||
|
|
||||||
from ..bioxel.layer import Layer
|
|
||||||
from ..bioxel.parse import parse_volumetric_data
|
|
||||||
from ..layer import save_layers_to_cache
|
|
||||||
|
|
||||||
|
|
||||||
def get_layer_shape(bioxel_size: float, orig_shape: tuple, orig_spacing: tuple):
|
def get_layer_shape(bioxel_size: float, orig_shape: tuple, orig_spacing: tuple):
|
||||||
shape = (
|
shape = (
|
||||||
@@ -62,6 +55,10 @@ def progress_callback_factory(progress_path: Path, cancel_path: Path, layer_name
|
|||||||
|
|
||||||
|
|
||||||
def read_meta(config, progress_path: Path, cancel_path: Path):
|
def read_meta(config, progress_path: Path, cancel_path: Path):
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from ..bioxel.parse import parse_volumetric_data
|
||||||
|
|
||||||
progress_callback = make_progress_writer(progress_path, cancel_path)
|
progress_callback = make_progress_writer(progress_path, cancel_path)
|
||||||
series_id = config["series_id"] if config["series_id"] != "empty" else ""
|
series_id = config["series_id"] if config["series_id"] != "empty" else ""
|
||||||
data, meta = parse_volumetric_data(
|
data, meta = parse_volumetric_data(
|
||||||
@@ -84,6 +81,13 @@ def read_meta(config, progress_path: Path, cancel_path: Path):
|
|||||||
|
|
||||||
|
|
||||||
def build_layers(config, progress_path: Path, cancel_path: Path):
|
def build_layers(config, progress_path: Path, cancel_path: Path):
|
||||||
|
import numpy as np
|
||||||
|
import transforms3d
|
||||||
|
|
||||||
|
from ..bioxel.layer import Layer
|
||||||
|
from ..bioxel.parse import parse_volumetric_data
|
||||||
|
from ..layer import save_layers_to_cache
|
||||||
|
|
||||||
write_json(progress_path, {"factor": 0.0, "text": "Parsing Volumetirc Data..."})
|
write_json(progress_path, {"factor": 0.0, "text": "Parsing Volumetirc Data..."})
|
||||||
progress_callback = make_progress_writer(progress_path, cancel_path, scale=0.2)
|
progress_callback = make_progress_writer(progress_path, cancel_path, scale=0.2)
|
||||||
data, meta = parse_volumetric_data(
|
data, meta = parse_volumetric_data(
|
||||||
@@ -231,6 +235,7 @@ def main(args):
|
|||||||
cancel_path = Path(config["cancel_path"])
|
cancel_path = Path(config["cancel_path"])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
write_json(progress_path, {"factor": 0.0, "text": "Loading import modules..."})
|
||||||
if config["command"] == "read_meta":
|
if config["command"] == "read_meta":
|
||||||
result = read_meta(config, progress_path, cancel_path)
|
result = read_meta(config, progress_path, cancel_path)
|
||||||
elif config["command"] == "import_layers":
|
elif config["command"] == "import_layers":
|
||||||
|
|||||||
Reference in New Issue
Block a user