-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: contrast formulation cause leak of high value fix: empty series_id cause fail to read chore: restructure folder chore!: change layer vars BREAKING CHANGE: not support 4.1 any more
- Loading branch information
Showing
57 changed files
with
3,062 additions
and
4,595 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,4 +133,4 @@ blendcache_* | |
|
||
.secrets | ||
|
||
!bioxelnodes/scipy/_nd_image.cp311-win_amd64.pyd | ||
!scipy_ndimage/*/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Git LFS file not shown
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from .layer import Layer | ||
|
||
|
||
class Container(): | ||
def __init__(self, | ||
name, | ||
layers: list[Layer] = []) -> None: | ||
self.name = name | ||
self.layers = layers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from pathlib import Path | ||
import uuid | ||
|
||
|
||
# 3rd-party | ||
import h5py | ||
|
||
from .container import Container | ||
from .layer import Layer | ||
|
||
|
||
def load_container(load_file: str): | ||
load_path = Path(load_file).resolve() | ||
with h5py.File(load_path, 'r') as file: | ||
layers = [] | ||
for key, layer_dset in file['layers'].items(): | ||
layers.append(Layer(data=layer_dset[:], | ||
name=layer_dset.attrs['name'], | ||
kind=layer_dset.attrs['kind'], | ||
affine=layer_dset.attrs['affine'])) | ||
|
||
container = Container(name=file.attrs['name'], | ||
layers=layers) | ||
|
||
return container | ||
|
||
|
||
def save_container(container: Container, save_file: str, overwrite=False): | ||
save_path = Path(save_file).resolve() | ||
if overwrite: | ||
if save_path.is_file(): | ||
save_path.unlink() | ||
|
||
with h5py.File(save_path, "w") as file: | ||
file.attrs['name'] = container.name | ||
layer_group = file.create_group("layers") | ||
for layer in container.layers: | ||
layer_key = uuid.uuid4().hex[:8] | ||
layer_dset = layer_group.create_dataset(name=layer_key, | ||
data=layer.data) | ||
layer_dset.attrs['name'] = layer.name | ||
layer_dset.attrs['kind'] = layer.kind | ||
layer_dset.attrs['affine'] = layer.affine |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import copy | ||
import numpy as np | ||
|
||
from . import scipy | ||
from . import skimage as ski | ||
|
||
# 3rd-party | ||
import transforms3d | ||
|
||
# TODO: turn to dataclasses | ||
|
||
|
||
class Layer(): | ||
def __init__(self, | ||
data: np.ndarray, | ||
name: str, | ||
kind="scalar", | ||
affine=np.identity(4)) -> None: | ||
if data.ndim != 5: | ||
raise Exception("Data shape order should be TXYZC") | ||
|
||
affine = np.array(affine) | ||
if affine.shape != (4, 4): | ||
raise Exception("affine shape should be (4,4)") | ||
|
||
self.data = data | ||
self.name = name | ||
self.kind = kind | ||
self.affine = affine | ||
|
||
@property | ||
def bioxel_size(self): | ||
t, r, z, s = transforms3d.affines.decompose44(self.affine) | ||
return z.tolist() | ||
|
||
@property | ||
def shape(self): | ||
return self.data.shape[1:4] | ||
|
||
@property | ||
def dtype(self): | ||
return self.data.dtype | ||
|
||
@property | ||
def origin(self): | ||
t, r, z, s = transforms3d.affines.decompose44(self.affine) | ||
return t.tolist() | ||
|
||
@property | ||
def euler(self): | ||
t, r, z, s = transforms3d.affines.decompose44(self.affine) | ||
return list(transforms3d.euler.mat2euler(r)) | ||
|
||
@property | ||
def min(self): | ||
return float(np.min(self.data)) | ||
|
||
@property | ||
def frame_count(self): | ||
return self.data.shape[0] | ||
|
||
@property | ||
def channel_count(self): | ||
return self.data.shape[-1] | ||
|
||
@property | ||
def max(self): | ||
return float(np.max(self.data)) | ||
|
||
def copy(self): | ||
return copy.deepcopy(self) | ||
|
||
def fill(self, value: float, mask: np.ndarray): | ||
mask_frames = () | ||
if mask.ndim == 4: | ||
if mask.shape[0] != self.frame_count: | ||
raise Exception("Mask frame count is not same as ") | ||
for f in range(self.frame_count): | ||
mask_frame = mask[f, :, :, :] | ||
mask_frame = scipy.median_filter( | ||
mask_frame.astype(np.float32), size=2) | ||
mask_frames += (mask_frame,) | ||
elif mask.ndim == 3: | ||
for f in range(self.frame_count): | ||
mask_frame = mask[:, :, :] | ||
mask_frame = scipy.median_filter( | ||
mask_frame.astype(np.float32), size=2) | ||
mask_frames += (mask_frame,) | ||
else: | ||
raise Exception("Mask shape order should be TXYZ or XYZ") | ||
|
||
_mask = np.stack(mask_frames) | ||
_mask = np.expand_dims(_mask, axis=-1) | ||
self.data = _mask * value + (1-_mask) * self.data | ||
|
||
def resize(self, shape:tuple, progress_callback=None): | ||
if len(shape) != 3: | ||
raise Exception("Shape must be 3 dim") | ||
|
||
data = self.data | ||
|
||
# TXYZC > TXYZ | ||
if self.kind in ['label', 'scalar']: | ||
data = np.amax(data, -1) | ||
|
||
if self.kind in ['scalar']: | ||
dtype = data.dtype | ||
data = data.astype(np.float32) | ||
|
||
data_frames = () | ||
for f in range(self.frame_count): | ||
if progress_callback: | ||
progress_callback(f, self.frame_count) | ||
|
||
frame = ski.resize(data[f, :, :, :], | ||
shape, | ||
preserve_range=True, | ||
anti_aliasing=data.dtype.kind != "b") | ||
|
||
data_frames += (frame,) | ||
|
||
data = np.stack(data_frames) | ||
|
||
if self.kind in ['scalar']: | ||
data = data.astype(dtype) | ||
|
||
# TXYZ > TXYZC | ||
if self.kind in ['label', 'scalar']: | ||
data = np.expand_dims(data, axis=-1) # expend channel | ||
|
||
self.data = data |
Oops, something went wrong.