fix: relocate cannot work on missing layer
fix: import fail if label are all zero fix: add cutter name to node fix: cannot append node lib file on NAS (UNC path) fix: join component cause disappear feat: smooth label feat: better topo on cutout by range
This commit is contained in:
@@ -343,7 +343,7 @@ class AddCutter():
|
||||
if len(cut_nodes) == 0:
|
||||
cutter_node = add_node_to_graph("ObjectCutter",
|
||||
node_group,
|
||||
node_label=name,
|
||||
node_label=f"{self.cutter_type.capitalize()} Cutter",
|
||||
use_link=get_use_link())
|
||||
cutter_node.inputs[0].default_value = self.cutter_type.capitalize()
|
||||
cutter_node.inputs[1].default_value = cutter_obj
|
||||
|
||||
@@ -164,7 +164,7 @@ class ParseVolumetricData(bpy.types.Operator):
|
||||
read_as: bpy.props.EnumProperty(name="Read as",
|
||||
default="SCALAR",
|
||||
items=[("SCALAR", "Scalar", ""),
|
||||
("LABEL", "Labels", ""),
|
||||
("LABEL", "Label", ""),
|
||||
("COLOR", "Color", "")]) # type: ignore
|
||||
|
||||
series_id: bpy.props.EnumProperty(name="Select Series",
|
||||
@@ -284,6 +284,10 @@ class ParseVolumetricData(bpy.types.Operator):
|
||||
self.report({"ERROR"}, "Invaild label data.")
|
||||
return {'CANCELLED'}
|
||||
|
||||
if self.label_count == 0:
|
||||
self.report({"ERROR"}, "Get no label.")
|
||||
return {'CANCELLED'}
|
||||
|
||||
orig_shape = self.meta['xyz_shape']
|
||||
orig_spacing = self.meta['spacing']
|
||||
|
||||
@@ -418,8 +422,8 @@ class ParseVolumetricData(bpy.types.Operator):
|
||||
series_id = "empty"
|
||||
|
||||
label = "{:<20} {:>1}".format(f"{study_description}>{series_description}({series_modality})",
|
||||
f"({size_x}x{size_y})x{count}")
|
||||
|
||||
f"({size_x}x{size_y})x{count}")
|
||||
|
||||
series_items[series_id] = label
|
||||
|
||||
for series_id, label in series_items.items():
|
||||
@@ -500,10 +504,13 @@ class ImportVolumetricDataDialog(bpy.types.Operator):
|
||||
|
||||
label_count: bpy.props.IntProperty() # type: ignore
|
||||
|
||||
smooth: bpy.props.IntProperty(name="Smooth Size (Larger takes longer time)",
|
||||
default=3) # type: ignore
|
||||
|
||||
read_as: bpy.props.EnumProperty(name="Read as",
|
||||
default="SCALAR",
|
||||
items=[("SCALAR", "Scalar", ""),
|
||||
("LABEL", "Labels", ""),
|
||||
("LABEL", "Label", ""),
|
||||
("COLOR", "Color", "")]) # type: ignore
|
||||
|
||||
bioxel_size: bpy.props.FloatProperty(name="Bioxel Size (Larger size means small resolution)",
|
||||
@@ -616,12 +623,15 @@ class ImportVolumetricDataDialog(bpy.types.Operator):
|
||||
progress_callback = progress_callback_factory(name_i,
|
||||
progress,
|
||||
progress_step)
|
||||
label_data = data == np.full_like(data, i+1)
|
||||
label_data = label_data.astype(np.float32)
|
||||
try:
|
||||
layer = Layer(data=data == np.full_like(data, i+1),
|
||||
layer = Layer(data=label_data,
|
||||
name=name_i,
|
||||
kind=kind)
|
||||
|
||||
layer.resize(shape=shape,
|
||||
smooth=self.smooth,
|
||||
progress_callback=progress_callback)
|
||||
|
||||
layer.affine = affine
|
||||
@@ -924,6 +934,8 @@ class ImportVolumetricDataDialog(bpy.types.Operator):
|
||||
if self.read_as == "SCALAR":
|
||||
panel.prop(self, "split_channel",
|
||||
text=f"Split Channel as Multi Layer")
|
||||
elif self.read_as == "LABEL":
|
||||
panel.prop(self, "smooth")
|
||||
|
||||
panel.label(
|
||||
text="Dimension Order: [Frame, (X-axis,Y-axis,Z-axis), Channel]")
|
||||
|
||||
@@ -4,7 +4,6 @@ import bpy
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
||||
from ..exceptions import NoContent
|
||||
from ..bioxel.layer import Layer
|
||||
from ..bioxelutils.node import add_node_to_graph
|
||||
@@ -199,7 +198,7 @@ class RetimeLayer(bpy.types.Operator, LayerOperator):
|
||||
return self.execute(context)
|
||||
|
||||
|
||||
class RelocateLayer(bpy.types.Operator, LayerOperator):
|
||||
class RelocateLayer(bpy.types.Operator):
|
||||
bl_idname = "bioxelnodes.relocate_layer"
|
||||
bl_label = "Relocate Layer Cache"
|
||||
bl_description = "Relocate layer cache"
|
||||
@@ -207,6 +206,16 @@ class RelocateLayer(bpy.types.Operator, LayerOperator):
|
||||
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH") # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
layer_obj = get_selected_layer(context)
|
||||
if layer_obj == None:
|
||||
self.report({"WARNING"}, "Get no layer.")
|
||||
return {'FINISHED'}
|
||||
|
||||
self.operate(layer_obj, context)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def operate(self, layer_obj, context):
|
||||
layer_obj.data.filepath = self.filepath
|
||||
|
||||
@@ -259,7 +268,7 @@ class ResampleLayer(bpy.types.Operator, OutputLayerOperator):
|
||||
bl_description = "Resample value"
|
||||
bl_icon = "ALIASED"
|
||||
|
||||
smooth: bpy.props.IntProperty(name="Smooth Iteration",
|
||||
smooth: bpy.props.IntProperty(name="Smooth Size",
|
||||
default=0,
|
||||
soft_min=0, soft_max=5,
|
||||
options={"SKIP_SAVE"}) # type: ignore
|
||||
@@ -389,7 +398,7 @@ class FillByThreshold(bpy.types.Operator, FillOperator):
|
||||
if self.invert else data > self.threshold
|
||||
|
||||
new_layer = orig_layer.copy()
|
||||
new_layer.fill(self.fill_value, mask, 3)
|
||||
new_layer.fill(self.fill_value, mask, 0)
|
||||
new_layer.name = self.new_layer_name \
|
||||
or f"{orig_layer.name}_F-{self.threshold:.2f}"
|
||||
return new_layer
|
||||
@@ -419,7 +428,7 @@ class FillByRange(bpy.types.Operator, FillOperator):
|
||||
(data > self.from_min) & (data < self.from_max)
|
||||
|
||||
new_layer = orig_layer.copy()
|
||||
new_layer.fill(self.fill_value, mask, 3)
|
||||
new_layer.fill(self.fill_value, mask, 0)
|
||||
new_layer.name = self.new_layer_name \
|
||||
or f"{orig_layer.name}_F-{self.from_min:.2f}-{self.from_max:.2f}"
|
||||
return new_layer
|
||||
@@ -431,7 +440,7 @@ class FillByLabel(bpy.types.Operator, FillOperator):
|
||||
bl_description = "Fill value by label"
|
||||
bl_icon = "MESH_CAPSULE"
|
||||
|
||||
smooth: bpy.props.IntProperty(name="Smooth Iteration",
|
||||
smooth: bpy.props.IntProperty(name="Smooth Size",
|
||||
default=0,
|
||||
soft_min=0, soft_max=5,
|
||||
options={"SKIP_SAVE"}) # type: ignore
|
||||
@@ -451,7 +460,7 @@ class FillByLabel(bpy.types.Operator, FillOperator):
|
||||
mask = 1 - mask
|
||||
|
||||
new_layer = orig_layer.copy()
|
||||
new_layer.fill(self.fill_value, mask, 3)
|
||||
new_layer.fill(self.fill_value, mask, 0)
|
||||
new_layer.name = self.new_layer_name \
|
||||
or f"{orig_layer.name}_F-{label_layer.name}"
|
||||
return new_layer
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
|
||||
from ..bioxelutils.common import is_incompatible, local_lib_not_updated
|
||||
from ..bioxelutils.node import assign_node_group, get_node_group
|
||||
from ..bioxelutils.node import assign_node_tree, get_node_tree
|
||||
from ..utils import get_use_link
|
||||
|
||||
|
||||
@@ -41,14 +41,14 @@ class AddNode(bpy.types.Operator):
|
||||
"Current addon verison is not compatible to this file. If you insist on editing this file please keep the same addon version.")
|
||||
return {'CANCELLED'}
|
||||
|
||||
get_node_group(self.node_type, get_use_link())
|
||||
node_tree = get_node_tree(self.node_type, get_use_link())
|
||||
bpy.ops.node.add_node(
|
||||
'INVOKE_DEFAULT',
|
||||
type='GeometryNodeGroup',
|
||||
use_transform=True
|
||||
)
|
||||
node = bpy.context.active_node
|
||||
assign_node_group(node, self.node_type)
|
||||
assign_node_tree(node, node_tree)
|
||||
node.label = self.node_label
|
||||
|
||||
node.show_options = False
|
||||
|
||||
Reference in New Issue
Block a user