fix: bug fix
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -129,4 +129,6 @@ pythonlib*
|
|||||||
|
|
||||||
blendcache_*
|
blendcache_*
|
||||||
|
|
||||||
*.ipynb
|
*.ipynb
|
||||||
|
|
||||||
|
.secrets
|
||||||
BIN
bioxelnodes/assets/Nodes.blend
LFS
BIN
bioxelnodes/assets/Nodes.blend
LFS
Binary file not shown.
@@ -10,6 +10,7 @@ class ConvertToMesh(bpy.types.Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
bioxels_objs = []
|
bioxels_objs = []
|
||||||
|
|
||||||
for obj in bpy.context.selected_objects:
|
for obj in bpy.context.selected_objects:
|
||||||
bioxels_obj = get_bioxels_obj(obj)
|
bioxels_obj = get_bioxels_obj(obj)
|
||||||
if bioxels_obj:
|
if bioxels_obj:
|
||||||
|
|||||||
@@ -42,15 +42,13 @@ class InstallationError(Exception):
|
|||||||
class PackageInstaller():
|
class PackageInstaller():
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
log_dir: str,
|
||||||
|
requirements_dir: str,
|
||||||
pypi_mirror_provider='Default',
|
pypi_mirror_provider='Default',
|
||||||
log_dir: str = None,
|
|
||||||
requirements_dir: str = None
|
|
||||||
) -> None:
|
) -> None:
|
||||||
self.pypi_mirror_provider = pypi_mirror_provider
|
self.pypi_mirror_provider = pypi_mirror_provider
|
||||||
self.log_path: Path = Path(log_dir) if log_dir else \
|
self.log_path: Path = Path(log_dir)
|
||||||
Path(Path.home(), '.externalpackage', 'logs')
|
self.requirements_path: Path = Path(requirements_dir)
|
||||||
self.requirements_path: Path = Path(requirements_dir) if requirements_dir else \
|
|
||||||
Path(__file__).parent
|
|
||||||
|
|
||||||
def start_logging(self, logfile_name: str = 'side-packages-install') -> logging.Logger:
|
def start_logging(self, logfile_name: str = 'side-packages-install') -> logging.Logger:
|
||||||
"""
|
"""
|
||||||
@@ -233,7 +231,7 @@ class PackageInstaller():
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# path to python.exe
|
# path to python.exe
|
||||||
python_exe = Path(sys.executable).resolve()
|
python_exe = Path(sys.executable).resolve().as_posix()
|
||||||
|
|
||||||
# build the command list
|
# build the command list
|
||||||
cmd_list = [python_exe] + cmd_list
|
cmd_list = [python_exe] + cmd_list
|
||||||
@@ -293,12 +291,11 @@ class PackageInstaller():
|
|||||||
raise ValueError("Package name must be provided.")
|
raise ValueError("Package name must be provided.")
|
||||||
|
|
||||||
print(f"Installing {package}...")
|
print(f"Installing {package}...")
|
||||||
print(f"Using PyPI mirror:\
|
print(f"Using PyPI mirror: {self.pypi_mirror_provider}")
|
||||||
{self.pypi_mirror_provider} {self.pypi_mirror_url}")
|
|
||||||
|
|
||||||
self.run_python(["-m", "ensurepip"]),
|
self.run_python(["-m", "ensurepip"]),
|
||||||
self.run_python(["-m", "pip", "install", "--upgrade", "pip"])
|
self.run_python(["-m", "pip", "install", "--upgrade", "pip"])
|
||||||
result = self.run_python(["-m", "pip", "install", package])
|
result = self.run_python(["-m", "pip", "install", package, "--user"])
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -348,7 +345,7 @@ class EXTERNALPACKAGE_OT_Install_Package(bpy.types.Operator):
|
|||||||
bl_idname = 'externalpackage.install_package'
|
bl_idname = 'externalpackage.install_package'
|
||||||
bl_label = 'Install Given Python Package'
|
bl_label = 'Install Given Python Package'
|
||||||
bl_options = {'REGISTER', 'INTERNAL'}
|
bl_options = {'REGISTER', 'INTERNAL'}
|
||||||
|
|
||||||
package: bpy.props.StringProperty(
|
package: bpy.props.StringProperty(
|
||||||
name='Python Package',
|
name='Python Package',
|
||||||
description='Python Package to Install'
|
description='Python Package to Install'
|
||||||
@@ -384,7 +381,9 @@ class EXTERNALPACKAGE_OT_Install_Package(bpy.types.Operator):
|
|||||||
else:
|
else:
|
||||||
self.report(
|
self.report(
|
||||||
{'ERROR'},
|
{'ERROR'},
|
||||||
f"Error installing package. Please check the log files in \
|
f"""
|
||||||
'{preferences.log_dir}'."
|
Error installing package. Please check the log files
|
||||||
|
in {preferences.log_dir}.
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ class ExternalPackagePreferences():
|
|||||||
requirements_dir: bpy.props.StringProperty(
|
requirements_dir: bpy.props.StringProperty(
|
||||||
name="requirements.txt Directory",
|
name="requirements.txt Directory",
|
||||||
subtype='DIR_PATH',
|
subtype='DIR_PATH',
|
||||||
default=''
|
default=Path(__file__).parent.as_posix()
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
log_dir: bpy.props.StringProperty(
|
log_dir: bpy.props.StringProperty(
|
||||||
name="Python Log Directory",
|
name="Python Log Directory",
|
||||||
subtype='DIR_PATH',
|
subtype='DIR_PATH',
|
||||||
default=''
|
default=Path(Path.home(), '.externalpackage', 'logs').as_posix()
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
pypi_mirror_provider: bpy.props.StringProperty(
|
pypi_mirror_provider: bpy.props.StringProperty(
|
||||||
@@ -40,6 +40,7 @@ class ExternalPackagePreferences():
|
|||||||
row_import = col_main.row()
|
row_import = col_main.row()
|
||||||
row_import.prop(self, 'pypi_mirror_provider', text='Set PyPI Mirror')
|
row_import.prop(self, 'pypi_mirror_provider', text='Set PyPI Mirror')
|
||||||
|
|
||||||
|
|
||||||
installer = PackageInstaller(
|
installer = PackageInstaller(
|
||||||
pypi_mirror_provider=self.pypi_mirror_provider,
|
pypi_mirror_provider=self.pypi_mirror_provider,
|
||||||
log_dir=self.log_dir,
|
log_dir=self.log_dir,
|
||||||
|
|||||||
@@ -6,12 +6,27 @@ import numpy as np
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import mathutils
|
import mathutils
|
||||||
from .utils import calc_bbox_verts, get_bioxels_obj, show_message
|
from .utils import calc_bbox_verts, extract_last_number, get_bioxels_obj, show_message
|
||||||
from .nodes import custom_nodes
|
from .nodes import custom_nodes
|
||||||
|
|
||||||
SUPPORT_EXTS = ['.dcm', '.tif', '.tiff', '.png', '.bmp']
|
SUPPORT_EXTS = ['.dcm', '.tif', '.tiff', '.png', '.bmp']
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_files(filepath: str):
|
||||||
|
file_path = Path(filepath).resolve()
|
||||||
|
suffix = file_path.suffix
|
||||||
|
|
||||||
|
files = list(file_path.parent.iterdir())
|
||||||
|
files = [f for f in files if f.is_file() and f.suffix == suffix]
|
||||||
|
|
||||||
|
def last_number(file: Path):
|
||||||
|
return extract_last_number(file.stem)
|
||||||
|
|
||||||
|
files.sort(key=last_number)
|
||||||
|
files = [f.as_posix() for f in files]
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
def on_orig_spacing_changed(self, context):
|
def on_orig_spacing_changed(self, context):
|
||||||
if self.auto:
|
if self.auto:
|
||||||
self.auto = False
|
self.auto = False
|
||||||
@@ -122,12 +137,8 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
file_path = Path(self.filepath).resolve()
|
file_path = Path(self.filepath).resolve()
|
||||||
name = file_path.parent.stem
|
name = file_path.parent.name
|
||||||
suffix = file_path.suffix
|
files = get_data_files(self.filepath)
|
||||||
|
|
||||||
files = list(file_path.parent.iterdir())
|
|
||||||
files = [f.as_posix()
|
|
||||||
for f in files if f.is_file() and f.suffix == suffix]
|
|
||||||
|
|
||||||
import SimpleITK as sitk
|
import SimpleITK as sitk
|
||||||
image = sitk.ReadImage(files)
|
image = sitk.ReadImage(files)
|
||||||
@@ -174,7 +185,7 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
image_origin = image.GetOrigin()
|
image_origin = image.GetOrigin()
|
||||||
bioxels_scale = float(self.bioxels_scale)
|
bioxels_scale = float(self.bioxels_scale)
|
||||||
bioxel_size *= bioxels_scale
|
bioxel_size *= bioxels_scale
|
||||||
bioxel_origin = (
|
bioxels_origin = (
|
||||||
image_origin[0] * bioxels_scale,
|
image_origin[0] * bioxels_scale,
|
||||||
image_origin[1] * bioxels_scale,
|
image_origin[1] * bioxels_scale,
|
||||||
image_origin[2] * bioxels_scale,
|
image_origin[2] * bioxels_scale,
|
||||||
@@ -248,7 +259,7 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
).to_4x4()
|
).to_4x4()
|
||||||
|
|
||||||
mat_loc = mathutils.Matrix.Translation(
|
mat_loc = mathutils.Matrix.Translation(
|
||||||
mathutils.Vector(bioxel_origin))
|
mathutils.Vector(bioxels_origin))
|
||||||
mat_sca = mathutils.Matrix.Scale(bioxel_size, 4)
|
mat_sca = mathutils.Matrix.Scale(bioxel_size, 4)
|
||||||
mat_rot = mathutils.Matrix(
|
mat_rot = mathutils.Matrix(
|
||||||
np.array(direction).reshape((3, 3))
|
np.array(direction).reshape((3, 3))
|
||||||
@@ -269,10 +280,12 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
bioxels_obj['value_max'] = value_max
|
bioxels_obj['value_max'] = value_max
|
||||||
bioxels_obj['value_min'] = value_min
|
bioxels_obj['value_min'] = value_min
|
||||||
bioxels_obj['value_offset'] = value_offset
|
bioxels_obj['value_offset'] = value_offset
|
||||||
|
bioxels_obj['image_origin'] = mathutils.Vector(
|
||||||
|
bioxels_origin) / bioxel_size
|
||||||
|
bioxels_obj['bioxel_size'] = bioxel_size
|
||||||
bioxels_obj['bioxels_shape'] = bioxels_shape
|
bioxels_obj['bioxels_shape'] = bioxels_shape
|
||||||
bioxels_obj['bioxels_size'] = bioxels_size
|
bioxels_obj['bioxels_size'] = bioxels_size
|
||||||
bioxels_obj['bioxel_size'] = bioxel_size
|
bioxels_obj['bioxels_origin'] = bioxels_origin
|
||||||
bioxels_obj['bioxel_origin'] = bioxel_origin
|
|
||||||
bioxels_obj['bioxels_values'] = True
|
bioxels_obj['bioxels_values'] = True
|
||||||
|
|
||||||
bpy.ops.node.new_geometry_nodes_modifier()
|
bpy.ops.node.new_geometry_nodes_modifier()
|
||||||
@@ -284,7 +297,7 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
)
|
)
|
||||||
container_obj = bpy.context.active_object
|
container_obj = bpy.context.active_object
|
||||||
|
|
||||||
bbox_verts = calc_bbox_verts(bioxel_origin, bioxels_size)
|
bbox_verts = calc_bbox_verts(bioxels_origin, bioxels_size)
|
||||||
for index, vert in enumerate(container_obj.data.vertices):
|
for index, vert in enumerate(container_obj.data.vertices):
|
||||||
vert.co = bbox_verts[index]
|
vert.co = bbox_verts[index]
|
||||||
|
|
||||||
@@ -353,13 +366,7 @@ class ReadDICOM(bpy.types.Operator):
|
|||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
files = get_data_files(self.filepath)
|
||||||
file_path = Path(self.filepath).resolve()
|
|
||||||
suffix = file_path.suffix
|
|
||||||
|
|
||||||
files = list(file_path.parent.iterdir())
|
|
||||||
files = [f.as_posix()
|
|
||||||
for f in files if f.is_file() and f.suffix == suffix]
|
|
||||||
|
|
||||||
import SimpleITK as sitk
|
import SimpleITK as sitk
|
||||||
image = sitk.ReadImage(files)
|
image = sitk.ReadImage(files)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
from pathlib import Path
|
||||||
from .custom_nodes import CustomNodes
|
from .custom_nodes import CustomNodes
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ MENU_ITEMS = [
|
|||||||
'icon': 'EMPTY_DATA',
|
'icon': 'EMPTY_DATA',
|
||||||
'node_type': 'BioxelNodes_LPS-Slicer',
|
'node_type': 'BioxelNodes_LPS-Slicer',
|
||||||
'node_description': '',
|
'node_description': '',
|
||||||
'node_callback': add_driver_to_node_factory("origin", "Origin")
|
'node_callback': add_driver_to_node_factory("image_origin", "Origin")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': 'Axis Slicer',
|
'label': 'Axis Slicer',
|
||||||
@@ -103,7 +104,7 @@ MENU_ITEMS = [
|
|||||||
|
|
||||||
custom_nodes = CustomNodes(
|
custom_nodes = CustomNodes(
|
||||||
menu_items=MENU_ITEMS,
|
menu_items=MENU_ITEMS,
|
||||||
nodes_file="assets/Nodes.blend",
|
nodes_file=Path(__file__).parent/"assets/Nodes.blend",
|
||||||
root_label='BioxelNodes',
|
root_label='BioxelNodes',
|
||||||
root_icon="FILE_VOLUME",
|
root_icon="FILE_VOLUME",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import mathutils
|
import mathutils
|
||||||
|
|
||||||
def show_message(message = "", title = "Message Box", icon = 'INFO'):
|
|
||||||
|
def show_message(message="", title="Message Box", icon='INFO'):
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
self.layout.label(text=message)
|
self.layout.label(text=message)
|
||||||
|
|
||||||
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
bpy.context.window_manager.popup_menu(draw, title=title, icon=icon)
|
||||||
|
|
||||||
|
|
||||||
def calc_bbox_verts(origin, size):
|
def calc_bbox_verts(origin, size):
|
||||||
bbox_origin = mathutils.Vector(
|
bbox_origin = mathutils.Vector(
|
||||||
(-origin[0], -origin[2], -origin[1]))
|
(-origin[0], -origin[2], -origin[1]))
|
||||||
@@ -76,6 +78,28 @@ def get_bioxels_obj(current_obj):
|
|||||||
return bioxels_obj
|
return bioxels_obj
|
||||||
|
|
||||||
|
|
||||||
|
def extract_last_number(text):
|
||||||
|
# Initialize an empty string to store the digits
|
||||||
|
digits = ""
|
||||||
|
|
||||||
|
# Iterate through the characters in reverse order
|
||||||
|
started = False
|
||||||
|
for char in text[::-1]:
|
||||||
|
if char.isdigit():
|
||||||
|
started = True
|
||||||
|
# If the character is a digit, add it to the digits string
|
||||||
|
digits += char
|
||||||
|
else:
|
||||||
|
if started:
|
||||||
|
# If a non-digit character is encountered, stop the loop
|
||||||
|
break
|
||||||
|
|
||||||
|
# Reverse the digits string to get the correct order
|
||||||
|
last_number = digits[::-1]
|
||||||
|
|
||||||
|
return int(last_number)
|
||||||
|
|
||||||
|
|
||||||
def add_driver(target_prop, var_sources, expression):
|
def add_driver(target_prop, var_sources, expression):
|
||||||
|
|
||||||
driver = target_prop.driver_add("default_value")
|
driver = target_prop.driver_add("default_value")
|
||||||
|
|||||||
Reference in New Issue
Block a user