9 Commits

Author SHA1 Message Date
Ma Nan
caf184c327 Merge pull request #33 from OmooLab/feature/dev
chore: update version
2024-07-23 12:32:06 +08:00
488b05f062 chore: update version 2024-07-23 12:31:33 +08:00
Ma Nan
2447a47269 Merge pull request #32 from OmooLab/feature/dev
docs: update discord link
2024-07-23 12:29:36 +08:00
9380342b4f docs: update discord link 2024-07-23 12:27:52 +08:00
Ma Nan
9b36e9d911 Merge pull request #31 from OmooLab/feature/dev
Feature/dev
2024-07-23 12:05:18 +08:00
c9a961d5e8 fix some import issue 2024-07-23 12:04:30 +08:00
77878888ca fix: missing add .ima to DICOM_EXTS 2024-07-22 09:56:20 +08:00
Ma Nan
50e8564027 Merge pull request #30 from OmooLab/feature/dev
docs: update README
2024-07-22 09:06:50 +08:00
f07ac1c70c docs: update README 2024-07-22 09:05:52 +08:00
9 changed files with 184 additions and 110 deletions

View File

@@ -2,29 +2,33 @@
# Bioxel Nodes # Bioxel Nodes
![Static Badge](https://img.shields.io/badge/Blender-orange?style=for-the-badge&logo=blender&logoColor=white) [![For Blender](https://img.shields.io/badge/Blender-orange?style=for-the-badge&logo=blender&logoColor=white&color=black)](https://blender.org/)
![GitHub License](https://img.shields.io/github/license/OmooLab/BioxelNodes?style=for-the-badge) ![GitHub License](https://img.shields.io/github/license/OmooLab/BioxelNodes?style=for-the-badge&labelColor=black)
![GitHub Release](https://img.shields.io/github/v/release/OmooLab/BioxelNodes?style=for-the-badge) ![GitHub Release](https://img.shields.io/github/v/release/OmooLab/BioxelNodes?style=for-the-badge&labelColor=black)
![GitHub Repo stars](https://img.shields.io/github/stars/OmooLab/BioxelNodes?style=for-the-badge) ![GitHub Repo stars](https://img.shields.io/github/stars/OmooLab/BioxelNodes?style=for-the-badge&labelColor=black)
[![Discord](https://img.shields.io/discord/1265129134397587457?style=for-the-badge&logo=discord&label=Discord&labelColor=white&color=black)](https://discord.gg/pYkNyq2TjE)
Bioxel Nodes is a Blender addon for scientific volumetric data visualization. It using Blender's powerful **Geometry Nodes** and **Cycles** to process and render volumetric data. Bioxel Nodes is a Blender addon for scientific volumetric data visualization. It using Blender's powerful **Geometry Nodes** and **Cycles** to process and render volumetric data.
![cover](https://omoolab.github.io/BioxelNodes/latest/assets/cover.png) ![cover](https://omoolab.github.io/BioxelNodes/latest/assets/cover.png)
- Fantastic rendering result, also support EEVEE NEXT - Fantastic rendering result, also support EEVEE NEXT.
- Support multiple formats - Support multiple formats.
- Support 4D volumetric data - Support 4D volumetric data.
- All kinds of cutters - All kinds of cutters.
- Simple and powerful nodes - Simple and powerful nodes.
- Based on blender natively, can work without addon. - Based on blender natively, can work without addon.
**Click [Getting Started](https://omoolab.github.io/BioxelNodes/latest/installation) to begin your journey into visualizing volumetric data!** **Read the [getting started](https://omoolab.github.io/BioxelNodes/latest/installation) to begin your journey into visualizing volumetric data!**
Welcome to our [discord server](https://discord.gg/pYkNyq2TjE), if you have any problems with this add-on.
## Support Multiple Formats ## Support Multiple Formats
| Format | EXT | Test | | Format | EXT | Test |
| ------ | ---------------------------------------- | ------- | | ------ | ---------------------------------------- | ------- |
| DICOM | .dcm, .DICOM | ✅ pass | | DICOM | .dcm, .DCM, .DICOM, .ima, .IMA | ✅ pass |
| BMP | .bmp, .BMP | ✅ pass | | BMP | .bmp, .BMP | ✅ pass |
| JPEG | .jpg, .JPG, .jpeg, .JPEG | ✅ pass | | JPEG | .jpg, .JPG, .jpeg, .JPEG | ✅ pass |
| PNG | .png, .PNG | ✅ pass | | PNG | .png, .PNG | ✅ pass |
@@ -32,6 +36,8 @@ Bioxel Nodes is a Blender addon for scientific volumetric data visualization. It
| Nifti | .nia, .nii, .nii.gz, .hdr, .img, .img.gz | ✅ pass | | Nifti | .nia, .nii, .nii.gz, .hdr, .img, .img.gz | ✅ pass |
| Nrrd | .nrrd, .nhdr | ✅ pass | | Nrrd | .nrrd, .nhdr | ✅ pass |
| HDF5 | .hdf, .h4, .hdf4, .he2, .h5, .hdf5, .he5 | ✅ pass | | HDF5 | .hdf, .h4, .hdf4, .he2, .h5, .hdf5, .he5 | ✅ pass |
| OME | .ome.tiff, .ome.tif | ✅ pass |
| MRC | .mrc, .mrc.gz, .map, .map.gz | ✅ pass |
## Support 4D volumetric data ## Support 4D volumetric data
@@ -53,7 +59,7 @@ Bioxel Nodes is a Blender addon for scientific volumetric data visualization. It
- Only works with Cycles CPU , Cycles GPU (OptiX), EEVEE - Only works with Cycles CPU , Cycles GPU (OptiX), EEVEE
- Section surface cannot be generated when convert to mesh (will be supported soon) - Section surface cannot be generated when convert to mesh (will be supported soon)
## Compatibile to Newer Version ## Compatible to Newer Version
**Updating this addon may break old files, so read the following carefully before updating** **Updating this addon may break old files, so read the following carefully before updating**

View File

@@ -9,7 +9,7 @@ bl_info = {
"author": "Ma Nan", "author": "Ma Nan",
"description": "", "description": "",
"blender": (4, 1, 0), "blender": (4, 1, 0),
"version": (0, 2, 8), "version": (0, 2, 9),
"location": "File -> Import", "location": "File -> Import",
"warning": "", "warning": "",
"category": "Node" "category": "Node"

View File

@@ -175,6 +175,9 @@ class ParseVolumetricData(bpy.types.Operator):
progress_callback=progress_callback) progress_callback=progress_callback)
except CancelledByUser: except CancelledByUser:
return return
except RuntimeError:
self.has_error = True
return
if cancel(): if cancel():
return return
@@ -183,6 +186,8 @@ class ParseVolumetricData(bpy.types.Operator):
# Init cancel flag # Init cancel flag
self.is_cancelled = False self.is_cancelled = False
self.has_error = False
# Create the thread # Create the thread
self.thread = threading.Thread(target=parse_volumetric_data_func, self.thread = threading.Thread(target=parse_volumetric_data_func,
args=(self, context, lambda: self.is_cancelled)) args=(self, context, lambda: self.is_cancelled))
@@ -229,6 +234,11 @@ class ParseVolumetricData(bpy.types.Operator):
self.report({"WARNING"}, "Canncelled by user.") self.report({"WARNING"}, "Canncelled by user.")
return {'CANCELLED'} return {'CANCELLED'}
# Check if thread is cancelled by user
if self.has_error:
self.report({"ERROR"}, "Fail to parse, something went wrong.")
return {'CANCELLED'}
# If not canncelled... # If not canncelled...
for key, value in self.meta.items(): for key, value in self.meta.items():
print(f"{key}: {value}") print(f"{key}: {value}")
@@ -239,9 +249,12 @@ class ParseVolumetricData(bpy.types.Operator):
orig_spacing[1], orig_spacing[2]) orig_spacing[1], orig_spacing[2])
bioxel_size = max(min_size, 1.0) bioxel_size = max(min_size, 1.0)
layer_size = get_layer_size(orig_shape, layer_shape = get_layer_shape(1, orig_shape, orig_spacing)
layer_size = get_layer_size(layer_shape,
bioxel_size) bioxel_size)
log10 = math.floor(math.log10(max(*layer_size))) log10 = math.floor(math.log10(max(*layer_size)))
log10 = max(1,log10)
log10 = min(3,log10)
scene_scale = math.pow(10, -log10) scene_scale = math.pow(10, -log10)
if self.container: if self.container:
@@ -700,6 +713,7 @@ class ImportVolumetricDataDialog(bpy.types.Operator):
container.matrix_world = mat_ras2blender @ mat_scene_scale container.matrix_world = mat_ras2blender @ mat_scene_scale
container.name = container_name container.name = container_name
container.show_in_front = True
container.data.name = container_name container.data.name = container_name
container['bioxel_container'] = True container['bioxel_container'] = True
@@ -741,8 +755,8 @@ class ImportVolumetricDataDialog(bpy.types.Operator):
layer.hide_select = True layer.hide_select = True
layer.hide_render = True layer.hide_render = True
layer.hide_viewport = True layer.hide_viewport = True
layer.data.display.use_slice = True # layer.data.display.use_slice = True
layer.data.display.density = 1e-05 # layer.data.display.density = 1e-05
layer['bioxel_layer'] = True layer['bioxel_layer'] = True
layer['bioxel_layer_type'] = layer_info['type'] layer['bioxel_layer_type'] = layer_info['type']
@@ -811,11 +825,8 @@ class ImportVolumetricDataDialog(bpy.types.Operator):
# Change render setting for better result # Change render setting for better result
preferences = context.preferences.addons[__package__].preferences preferences = context.preferences.addons[__package__].preferences
if preferences.do_change_render_setting and self.is_first_import: if preferences.do_change_render_setting and self.is_first_import:
if bpy.app.version < (4, 2, 0): bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.render.engine = 'CYCLES'
try: try:
bpy.context.scene.cycles.shading_system = True bpy.context.scene.cycles.shading_system = True
bpy.context.scene.cycles.volume_bounces = 12 bpy.context.scene.cycles.volume_bounces = 12

View File

@@ -89,8 +89,8 @@ def deep_copy_layer(vdb_path, base_layer, name):
copyed_layer.hide_select = True copyed_layer.hide_select = True
copyed_layer.hide_render = True copyed_layer.hide_render = True
copyed_layer.hide_viewport = True copyed_layer.hide_viewport = True
copyed_layer.data.display.use_slice = True # copyed_layer.data.display.use_slice = True
copyed_layer.data.display.density = 1e-05 # copyed_layer.data.display.density = 1e-05
copyed_layer['bioxel_layer'] = True copyed_layer['bioxel_layer'] = True
copyed_layer['bioxel_layer_type'] = base_layer['bioxel_layer_type'] copyed_layer['bioxel_layer_type'] = base_layer['bioxel_layer_type']

View File

@@ -11,6 +11,9 @@ try:
except: except:
... ...
"""
Convert any volumetric data to 3D numpy array with order TXYZC
"""
SUPPORT_EXTS = ['', '.dcm', '.DCM', '.DICOM', '.ima', '.IMA', SUPPORT_EXTS = ['', '.dcm', '.DCM', '.DICOM', '.ima', '.IMA',
'.bmp', '.BMP', '.bmp', '.BMP',
@@ -40,7 +43,7 @@ SEQUENCE_EXTS = ['.bmp', '.BMP',
'.tif', '.TIF', '.tiff', '.TIFF', '.tif', '.TIF', '.tiff', '.TIFF',
'.png', '.PNG'] '.png', '.PNG']
DICOM_EXTS = ['', '.dcm', '.DCM', '.DICOM'] DICOM_EXTS = ['', '.dcm', '.DCM', '.DICOM', '.ima', '.IMA']
FH_EXTS = ['', '.dcm', '.DCM', '.DICOM', '.ima', '.IMA', FH_EXTS = ['', '.dcm', '.DCM', '.DICOM', '.ima', '.IMA',
'.gipl', '.gipl.gz', '.gipl', '.gipl.gz',
@@ -136,7 +139,11 @@ def parse_volumetric_data(filepath: str, series_id="", progress_callback=None):
if len(sequence) > 1: if len(sequence) > 1:
is_sequence = True is_sequence = True
if ext in MRC_EXTS and not is_sequence: volume = None
# Parsing with mrcfile
if volume is None and ext in MRC_EXTS and not is_sequence:
print("Parsing with mrcfile...")
# TODO: much to do with mrc # TODO: much to do with mrc
with mrcfile.open(filepath) as mrc: with mrcfile.open(filepath) as mrc:
volume = mrc.data volume = mrc.data
@@ -159,10 +166,10 @@ def parse_volumetric_data(filepath: str, series_id="", progress_callback=None):
elif mrc.is_volume_stack(): elif mrc.is_volume_stack():
volume = np.expand_dims(volume, axis=-1) # expend channel volume = np.expand_dims(volume, axis=-1) # expend channel
name = Path(filepath).name.removesuffix(ext).replace(" ", "-") name = Path(filepath).name.removesuffix(ext).replace(" ", "-")
shape = volume.shape[1:4] shape = volume.shape[1:4]
spacing = (mrc.voxel_size.x, mrc.voxel_size.y, mrc.voxel_size.z) spacing = (mrc.voxel_size.x, mrc.voxel_size.y, mrc.voxel_size.z)
meta = { meta = {
"name": name, "name": name,
"description": "", "description": "",
@@ -175,7 +182,9 @@ def parse_volumetric_data(filepath: str, series_id="", progress_callback=None):
"is_oriented": False "is_oriented": False
} }
elif ext in OME_EXTS and not is_sequence: # Parsing with OMETIFFReader
if volume is None and ext in OME_EXTS and not is_sequence:
print("Parsing with OMETIFFReader...")
reader = OMETIFFReader(fpath=filepath) reader = OMETIFFReader(fpath=filepath)
ome_volume, metadata, xml_metadata = reader.read() ome_volume, metadata, xml_metadata = reader.read()
@@ -189,69 +198,70 @@ def parse_volumetric_data(filepath: str, series_id="", progress_callback=None):
# for key in metadata: # for key in metadata:
# print(f"{key},{metadata[key]}") # print(f"{key},{metadata[key]}")
ome_order = metadata['DimOrder BF Array'] ome_order = metadata['DimOrder BF Array']
if ome_volume.ndim == 2:
ome_order = ome_order.replace("T", "")\
.replace("C", "").replace("Z", "")
bioxel_order = (ome_order.index('X'),
ome_order.index('Y'))
volume = np.transpose(ome_volume, bioxel_order)
volume = np.expand_dims(volume, axis=0) # expend frame
volume = np.expand_dims(volume, axis=-1) # expend Z
volume = np.expand_dims(volume, axis=-1) # expend channel
elif ome_volume.ndim == 3:
# -> XYZC
ome_order = ome_order.replace("T", "").replace("C", "")
bioxel_order = (ome_order.index('X'),
ome_order.index('Y'),
ome_order.index('Z'))
volume = np.transpose(ome_volume, bioxel_order)
volume = np.expand_dims(volume, axis=0) # expend frame
volume = np.expand_dims(volume, axis=-1) # expend channel
elif ome_volume.ndim == 4:
# -> XYZC
ome_order = ome_order.replace("T", "")
bioxel_order = (ome_order.index('X'),
ome_order.index('Y'),
ome_order.index('Z'),
ome_order.index('C'))
volume = np.transpose(ome_volume, bioxel_order)
volume = np.expand_dims(volume, axis=0) # expend frame
elif ome_volume.ndim == 5:
# -> TXYZC
bioxel_order = (ome_order.index('T'),
ome_order.index('X'),
ome_order.index('Y'),
ome_order.index('Z'),
ome_order.index('C'))
volume = np.transpose(ome_volume, bioxel_order)
shape = volume.shape[1:4]
try:
spacing = (metadata['PhysicalSizeX'],
metadata['PhysicalSizeY'],
metadata['PhysicalSizeZ'])
except:
spacing = (1, 1, 1)
name = Path(filepath).name.removesuffix(ext).replace(" ", "-")
meta = {
"name": name,
"description": "",
"shape": shape,
"spacing": spacing,
"origin": (0, 0, 0),
"direction": (1, 0, 0, 0, 1, 0, 0, 0, 1),
"frame_count": volume.shape[0],
"channel_count": volume.shape[-1],
"is_oriented": False
}
except: except:
ome_order = "TCZYX" ...
if ome_volume.ndim == 2: # Parsing with SimpleITK
ome_order = ome_order.replace("T", "")\ if volume is None:
.replace("C", "").replace("Z", "") print("Parsing with SimpleITK...")
bioxel_order = (ome_order.index('X'),
ome_order.index('Y'))
volume = np.transpose(ome_volume, bioxel_order)
volume = np.expand_dims(volume, axis=0) # expend frame
volume = np.expand_dims(volume, axis=-1) # expend Z
volume = np.expand_dims(volume, axis=-1) # expend channel
elif ome_volume.ndim == 3:
# -> XYZC
ome_order = ome_order.replace("T", "").replace("C", "")
bioxel_order = (ome_order.index('X'),
ome_order.index('Y'),
ome_order.index('Z'))
volume = np.transpose(ome_volume, bioxel_order)
volume = np.expand_dims(volume, axis=0) # expend frame
volume = np.expand_dims(volume, axis=-1) # expend channel
elif ome_volume.ndim == 4:
# -> XYZC
ome_order = ome_order.replace("T", "")
bioxel_order = (ome_order.index('X'),
ome_order.index('Y'),
ome_order.index('Z'),
ome_order.index('C'))
volume = np.transpose(ome_volume, bioxel_order)
volume = np.expand_dims(volume, axis=0) # expend frame
elif ome_volume.ndim == 5:
# -> TXYZC
bioxel_order = (ome_order.index('T'),
ome_order.index('X'),
ome_order.index('Y'),
ome_order.index('Z'),
ome_order.index('C'))
volume = np.transpose(ome_volume, bioxel_order)
shape = volume.shape[1:4]
try:
spacing = (metadata['PhysicalSizeX'],
metadata['PhysicalSizeY'],
metadata['PhysicalSizeZ'])
except:
spacing = (1, 1, 1)
name = Path(filepath).name.removesuffix(ext).replace(" ", "-")
meta = {
"name": name,
"description": "",
"shape": shape,
"spacing": spacing,
"origin": (0, 0, 0),
"direction": (1, 0, 0, 0, 1, 0, 0, 0, 1),
"frame_count": volume.shape[0],
"channel_count": volume.shape[-1],
"is_oriented": False
}
else:
if ext in DICOM_EXTS: if ext in DICOM_EXTS:
dir_path = Path(filepath).resolve().parent dir_path = Path(filepath).resolve().parent
reader = sitk.ImageSeriesReader() reader = sitk.ImageSeriesReader()
@@ -294,10 +304,13 @@ def parse_volumetric_data(filepath: str, series_id="", progress_callback=None):
name = name.replace(" ", "-") name = name.replace(" ", "-")
description = description.replace(" ", "-") description = description.replace(" ", "-")
elif ext in SEQUENCE_EXTS: elif ext in SEQUENCE_EXTS and is_sequence:
itk_volume = sitk.ReadImage(sequence) try:
name = get_sequence_name(filepath).replace(" ", "-") itk_volume = sitk.ReadImage(sequence)
description = "" name = get_sequence_name(filepath).replace(" ", "-")
description = ""
except RuntimeError as e:
raise e
else: else:
itk_volume = sitk.ReadImage(filepath) itk_volume = sitk.ReadImage(filepath)
name = Path(filepath).name.removesuffix(ext).replace(" ", "-") name = Path(filepath).name.removesuffix(ext).replace(" ", "-")
@@ -311,7 +324,33 @@ def parse_volumetric_data(filepath: str, series_id="", progress_callback=None):
if not progressing: if not progressing:
raise CancelledByUser raise CancelledByUser
if itk_volume.GetDimension() == 3: if itk_volume.GetDimension() == 2:
volume = sitk.GetArrayFromImage(itk_volume)
if volume.ndim == 3:
volume = np.transpose(volume, (1, 0, 2))
volume = np.expand_dims(volume, axis=-2) # expend Z
else:
volume = np.transpose(volume)
volume = np.expand_dims(volume, axis=-1) # expend Z
volume = np.expand_dims(volume, axis=-1) # expend channel
volume = np.expand_dims(volume, axis=0) # expend frame
meta = {
"name": name,
"description": description,
"shape": volume.shape[1:4],
"spacing": (1, 1, 1),
"origin": (0, 0, 0),
"direction": (1, 0, 0, 0, 1, 0, 0, 0, 1),
"frame_count": 1,
"channel_count": volume.shape[-1],
"is_oriented": False
}
elif itk_volume.GetDimension() == 3:
itk_volume = sitk.DICOMOrient(itk_volume, 'RAS') itk_volume = sitk.DICOMOrient(itk_volume, 'RAS')
volume = sitk.GetArrayFromImage(itk_volume) volume = sitk.GetArrayFromImage(itk_volume)
@@ -332,12 +371,12 @@ def parse_volumetric_data(filepath: str, series_id="", progress_callback=None):
"spacing": tuple(itk_volume.GetSpacing()), "spacing": tuple(itk_volume.GetSpacing()),
"origin": tuple(itk_volume.GetOrigin()), "origin": tuple(itk_volume.GetOrigin()),
"direction": tuple(itk_volume.GetDirection()), "direction": tuple(itk_volume.GetDirection()),
"frame_count": volume.shape[0], "frame_count": 1,
"channel_count": volume.shape[-1], "channel_count": volume.shape[-1],
"is_oriented": True "is_oriented": True
} }
if itk_volume.GetDimension() == 4: elif itk_volume.GetDimension() == 4:
# FIXME: not sure... # FIXME: not sure...
direction = np.array(itk_volume.GetDirection()) direction = np.array(itk_volume.GetDirection())
direction = direction.reshape(3, 3) if itk_volume.GetDimension() == 3 \ direction = direction.reshape(3, 3) if itk_volume.GetDimension() == 3 \

View File

@@ -1,23 +1,34 @@
[中文文档](https://uj6xfhbzp0.feishu.cn/wiki/Qx3VwHuNPimeI8kr6nDcvl1DnHf?from=from_copylink)
# Bioxel Nodes # Bioxel Nodes
[![For Blender](https://img.shields.io/badge/Blender-orange?style=for-the-badge&logo=blender&logoColor=white&color=black)](https://blender.org/)
![GitHub License](https://img.shields.io/github/license/OmooLab/BioxelNodes?style=for-the-badge&labelColor=black)
![GitHub Release](https://img.shields.io/github/v/release/OmooLab/BioxelNodes?style=for-the-badge&labelColor=black)
![GitHub Repo stars](https://img.shields.io/github/stars/OmooLab/BioxelNodes?style=for-the-badge&labelColor=black)
[![Discord](https://img.shields.io/discord/1265129134397587457?style=for-the-badge&logo=discord&label=Discord&labelColor=white&color=black)](https://discord.gg/pYkNyq2TjE)
Bioxel Nodes is a Blender addon for scientific volumetric data visualization. It using Blender's powerful **Geometry Nodes** and **Cycles** to process and render volumetric data. Bioxel Nodes is a Blender addon for scientific volumetric data visualization. It using Blender's powerful **Geometry Nodes** and **Cycles** to process and render volumetric data.
![cover](assets/cover.png) ![cover](https://omoolab.github.io/BioxelNodes/latest/assets/cover.png)
- Fantastic rendering result, also support EEVEE NEXT - Fantastic rendering result, also support EEVEE NEXT.
- Support multiple formats - Support multiple formats.
- Support 4D volumetric data - Support 4D volumetric data.
- All kinds of cutters - All kinds of cutters.
- Simple and powerful nodes - Simple and powerful nodes.
- Based on blender natively, can work without addon. - Based on blender natively, can work without addon.
**Click [Getting Started](https://omoolab.github.io/BioxelNodes/latest/installation) to begin your journey into visualizing volumetric data!** **Read the [getting started](https://omoolab.github.io/BioxelNodes/latest/installation) to begin your journey into visualizing volumetric data!**
Welcome to our [discord server](https://discord.gg/pYkNyq2TjE), if you have any problems with this add-on.
## Support Multiple Formats ## Support Multiple Formats
| Format | EXT | Test | | Format | EXT | Test |
| ------ | ---------------------------------------- | ------- | | ------ | ---------------------------------------- | ------- |
| DICOM | .dcm, .DICOM | ✅ pass | | DICOM | .dcm, .DCM, .DICOM, .ima, .IMA | ✅ pass |
| BMP | .bmp, .BMP | ✅ pass | | BMP | .bmp, .BMP | ✅ pass |
| JPEG | .jpg, .JPG, .jpeg, .JPEG | ✅ pass | | JPEG | .jpg, .JPG, .jpeg, .JPEG | ✅ pass |
| PNG | .png, .PNG | ✅ pass | | PNG | .png, .PNG | ✅ pass |
@@ -25,6 +36,8 @@ Bioxel Nodes is a Blender addon for scientific volumetric data visualization. It
| Nifti | .nia, .nii, .nii.gz, .hdr, .img, .img.gz | ✅ pass | | Nifti | .nia, .nii, .nii.gz, .hdr, .img, .img.gz | ✅ pass |
| Nrrd | .nrrd, .nhdr | ✅ pass | | Nrrd | .nrrd, .nhdr | ✅ pass |
| HDF5 | .hdf, .h4, .hdf4, .he2, .h5, .hdf5, .he5 | ✅ pass | | HDF5 | .hdf, .h4, .hdf4, .he2, .h5, .hdf5, .he5 | ✅ pass |
| OME | .ome.tiff, .ome.tif | ✅ pass |
| MRC | .mrc, .mrc.gz, .map, .map.gz | ✅ pass |
## Support 4D volumetric data ## Support 4D volumetric data
@@ -46,7 +59,7 @@ Bioxel Nodes is a Blender addon for scientific volumetric data visualization. It
- Only works with Cycles CPU , Cycles GPU (OptiX), EEVEE - Only works with Cycles CPU , Cycles GPU (OptiX), EEVEE
- Section surface cannot be generated when convert to mesh (will be supported soon) - Section surface cannot be generated when convert to mesh (will be supported soon)
## Compatibile to Newer Version ## Compatible to Newer Version
**Updating this addon may break old files, so read the following carefully before updating** **Updating this addon may break old files, so read the following carefully before updating**
@@ -57,6 +70,7 @@ After the addon update, your old project files may not work either, this may be
Also, unlike the newer versions, the older shaders are not based on OSL, so if you find that you can't render volumes, you need to turn on **Open Shading Language (OSL)** in the Render Settings. Also, unlike the newer versions, the older shaders are not based on OSL, so if you find that you can't render volumes, you need to turn on **Open Shading Language (OSL)** in the Render Settings.
## Roadmap ## Roadmap
- Better multi-format import experience
- One-click bake model with texture - Better multi-format import experience
- AI Segmentation to Generate Labels - One-click bake model with texture
- AI Segmentation to Generate Labels

View File

@@ -6,7 +6,7 @@ First thing first, you need to get your volumetric data ready in disk. Bioxel No
| Format | EXT | Test | | Format | EXT | Test |
| ------ | ---------------------------------------- | ------- | | ------ | ---------------------------------------- | ------- |
| DICOM | .dcm, .DICOM | ✅ pass | | DICOM | .dcm, .DCM, .DICOM, .ima, .IMA | ✅ pass |
| BMP | .bmp, .BMP | ✅ pass | | BMP | .bmp, .BMP | ✅ pass |
| JPEG | .jpg, .JPG, .jpeg, .JPEG | ✅ pass | | JPEG | .jpg, .JPG, .jpeg, .JPEG | ✅ pass |
| PNG | .png, .PNG | ✅ pass | | PNG | .png, .PNG | ✅ pass |
@@ -21,6 +21,8 @@ First thing first, you need to get your volumetric data ready in disk. Bioxel No
| LSM | .lsm, .LSM | yet | | LSM | .lsm, .LSM | yet |
| MINC | .mnc, .MNC | yet | | MINC | .mnc, .MNC | yet |
| MRC | .mrc, .rec | yet | | MRC | .mrc, .rec | yet |
| OME | .ome.tiff, .ome.tif | ✅ pass |
| MRC | .mrc, .mrc.gz, .map, .map.gz | ✅ pass |
## Download Data from Internet ## Download Data from Internet
@@ -32,10 +34,12 @@ If you don't have any volumetric data, you can access open research data from li
| ------------------------------------------------------------------------------------ | ------------------ | | ------------------------------------------------------------------------------------ | ------------------ |
| [MorphoSource](https://www.morphosource.org/) | Open Research Data | | [MorphoSource](https://www.morphosource.org/) | Open Research Data |
| [Dryad](https://datadryad.org) | Open Research Data | | [Dryad](https://datadryad.org) | Open Research Data |
| [Cell Image Library](http://cellimagelibrary.org/home) | Cells |
| [OpenOrganelle](https://openorganelle.janelia.org/datasets) | Cells | | [OpenOrganelle](https://openorganelle.janelia.org/datasets) | Cells |
| [Allen Cell Explorer](https://www.allencell.org/3d-cell-viewer.html) | Cells |
| [EMDB](https://www.ebi.ac.uk/emdb/) | Protein, Viruses |
| [Embodi3D](https://www.embodi3d.com/files/category/37-medical-scans/) | Medical Images | | [Embodi3D](https://www.embodi3d.com/files/category/37-medical-scans/) | Medical Images |
| [Github](https://github.com/sfikas/medical-imaging-datasets) | Medical Images | | [Github](https://github.com/sfikas/medical-imaging-datasets) | Medical Images |
| [NIHR](https://nhsx.github.io/open-source-imaging-data-sets/) | Medical Images | | [NIHR](https://nhsx.github.io/open-source-imaging-data-sets/) | Medical Images |
| [Medical Segmentation Decathlon](http://medicaldecathlon.com/) | Medical Images | | [Medical Segmentation Decathlon](http://medicaldecathlon.com/) | Medical Images |
| [Allen Cell Explorer](https://www.allencell.org/3d-cell-viewer.html) | Cells |
| [Visible Human Project](https://www.nlm.nih.gov/research/visible/visible_human.html) | Medical Images | | [Visible Human Project](https://www.nlm.nih.gov/research/visible/visible_human.html) | Medical Images |

View File

@@ -3,7 +3,7 @@ schema_version = "1.0.0"
# Example of manifest file for a Blender extension # Example of manifest file for a Blender extension
# Change the values according to your extension # Change the values according to your extension
id = "bioxelnodes" id = "bioxelnodes"
version = "0.2.8" version = "0.2.9"
name = "Bioxel Nodes" name = "Bioxel Nodes"
tagline = "For scientific volumetric data visualization in Blender" tagline = "For scientific volumetric data visualization in Blender"
maintainer = "Ma Nan <icrdr2010@outlook.com>" maintainer = "Ma Nan <icrdr2010@outlook.com>"

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "bioxelnodes" name = "bioxelnodes"
version = "0.2.8" version = "0.2.9"
description = "" description = ""
authors = ["Ma Nan <icrdr2010@outlook.com>"] authors = ["Ma Nan <icrdr2010@outlook.com>"]
license = "MIT" license = "MIT"