Skip to content

Commit a05fa95

Browse files
committed
wip zarr impl
1 parent 4ee472b commit a05fa95

File tree

4 files changed

+134
-33
lines changed

4 files changed

+134
-33
lines changed

matlab/rust/wkw_load/Cargo.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ version = "1.4.0"
44
authors = ["Alessandro Motta <[email protected]>"]
55
build = "build.rs"
66

7-
[dependencies.wkwrap]
8-
path = "../../../rust"
9-
10-
[dependencies.wkw_mex]
11-
path = "../wkw_mex"
7+
[dependencies]
8+
wkwrap = { path = "../../../rust" }
9+
zarrs = "0.22.4"
10+
wkw_mex = { path = "../wkw_mex" }
1211

1312
[profile.release]
1413
lto = true

matlab/rust/wkw_load/src/lib.rs

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,126 @@
11
extern crate wkwrap;
2+
extern crate zarrs;
23

34
#[macro_use]
45
extern crate wkw_mex;
56
use wkw_mex::*;
7+
use wkwrap::{Box3, Mat, Vec3, VoxelType};
8+
use zarrs::array::data_type::DataType;
9+
use zarrs::array::Array;
10+
use zarrs::array_subset::ArraySubset;
611

12+
use std::path::PathBuf;
713
use std::slice;
8-
use std::path::Path;
14+
use std::sync::Arc;
15+
16+
fn zarrs_result_to_str_error<T, E: std::error::Error>(
17+
result: std::result::Result<T, E>,
18+
) -> Result<T> {
19+
match result {
20+
Ok(ok) => Ok(ok),
21+
Err(err) => Err(err.to_string()),
22+
}
23+
}
924

1025
mex_function!(nlhs, lhs, nrhs, rhs, {
1126
let rhs = match nrhs == 2 {
1227
true => slice::from_raw_parts(rhs, nrhs as usize),
13-
false => return Err("Invalid number of input arguments".to_string())
28+
false => return Err("Invalid number of input arguments".to_string()),
1429
};
1530

1631
let lhs = match nlhs == 1 {
1732
true => slice::from_raw_parts_mut(lhs, nlhs as usize),
18-
false => return Err("Invalid number of output arguments".to_string())
33+
false => return Err("Invalid number of output arguments".to_string()),
1934
};
2035

21-
let wkw_path = mx_array_to_str(rhs[0])?;
22-
let dataset_path = Path::new(wkw_path);
23-
let dataset = wkwrap::Dataset::new(dataset_path)?;
36+
let store_path: PathBuf = mx_array_to_str(rhs[0])?.into();
37+
38+
let store: zarrs::storage::ReadableWritableListableStorage = Arc::new(
39+
zarrs_result_to_str_error(zarrs::filesystem::FilesystemStore::new(&store_path))?,
40+
);
41+
let array = zarrs_result_to_str_error(Array::open(store.clone(), "/"))?;
2442

25-
let num_channels = dataset.header().num_channels();
43+
let num_channels = array.shape()[0] as usize;
2644
let is_multi_channel = num_channels > 1;
2745

2846
// build shape
2947
let bbox = mx_array_to_wkwrap_box(rhs[1])?;
30-
let shape = bbox.width();
48+
let subset = zarrs_result_to_str_error(ArraySubset::new_with_start_shape(
49+
vec![
50+
0,
51+
bbox.min().x as u64,
52+
bbox.min().y as u64,
53+
bbox.min().z as u64,
54+
],
55+
vec![
56+
1,
57+
bbox.width().x as u64,
58+
bbox.width().y as u64,
59+
bbox.width().z as u64,
60+
],
61+
))?;
3162

32-
let shape_arr = [num_channels, shape.x as usize, shape.y as usize, shape.z as usize];
33-
let shape_slice = if is_multi_channel { &shape_arr[0..] } else { &shape_arr[1..] };
63+
let shape_arr = [
64+
num_channels,
65+
bbox.width().x as usize,
66+
bbox.width().y as usize,
67+
bbox.width().z as usize,
68+
];
69+
let shape_slice = if is_multi_channel {
70+
&shape_arr[0..]
71+
} else {
72+
&shape_arr[1..]
73+
};
3474

3575
// prepare allocation
36-
let voxel_type = dataset.header().voxel_type;
37-
let class = voxel_type_to_mx_class_id(voxel_type);
76+
let voxel_type = match array.data_type() {
77+
DataType::UInt8 => VoxelType::U8,
78+
DataType::UInt16 => VoxelType::U16,
79+
DataType::UInt32 => VoxelType::U32,
80+
DataType::UInt64 => VoxelType::U64,
81+
DataType::Float32 => VoxelType::F32,
82+
DataType::Float64 => VoxelType::F64,
83+
DataType::Int8 => VoxelType::I8,
84+
DataType::Int16 => VoxelType::I16,
85+
DataType::Int32 => VoxelType::I32,
86+
DataType::Int64 => VoxelType::I64,
87+
_ => {
88+
return Err("Unsupported data type".to_string());
89+
}
90+
};
91+
let class = match array.data_type() {
92+
DataType::UInt8 => MxClassId::Uint8,
93+
DataType::UInt16 => MxClassId::Uint16,
94+
DataType::UInt32 => MxClassId::Uint32,
95+
DataType::UInt64 => MxClassId::Uint64,
96+
DataType::Float32 => MxClassId::Single,
97+
DataType::Float64 => MxClassId::Double,
98+
DataType::Int8 => MxClassId::Int8,
99+
DataType::Int16 => MxClassId::Int16,
100+
DataType::Int32 => MxClassId::Int32,
101+
DataType::Int64 => MxClassId::Int64,
102+
_ => {
103+
return Err("Unsupported data type".to_string());
104+
}
105+
};
38106

39107
// read data
108+
let data_all = zarrs_result_to_str_error(array.retrieve_array_subset(&subset))?;
109+
let mut buf = zarrs_result_to_str_error(data_all.into_fixed())?.into_owned(); // in c-order
110+
let src_mat = Mat::new(
111+
&mut buf,
112+
bbox.width(),
113+
voxel_type.size() * num_channels,
114+
voxel_type,
115+
true,
116+
)?;
40117
let arr = create_numeric_array(shape_slice, class, MxComplexity::Real)?;
41118
let mut mat = mx_array_mut_to_wkwrap_mat(is_multi_channel, arr)?;
42-
dataset.read_mat(bbox.min(), &mut mat)?;
119+
120+
src_mat.copy_as_fortran_order(
121+
&mut mat,
122+
Box3::new(Vec3 { x: 0, y: 0, z: 0 }, bbox.width())?,
123+
)?;
43124

44125
// set output
45126
lhs[0] = arr;

matlab/rust/wkw_mex/src/ffi.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
pub use libc::{c_double, c_int, c_uchar, c_uint, c_void, size_t};
12
pub use std::os::raw::c_char;
2-
pub use libc::{c_void, c_uchar, c_int, c_uint, c_double, size_t};
33

44
// HACK(amotta): There is no guarantee for this
55
#[allow(non_camel_case_types)]
@@ -12,28 +12,49 @@ pub type MxArrayMut = *mut MxArrayT;
1212
// HACK(amotta): This is only true for the new, 64bit API
1313
pub type MwSize = size_t;
1414

15-
pub enum MxComplexity { Real, Complex }
15+
pub enum MxComplexity {
16+
Real,
17+
Complex,
18+
}
1619

1720
#[repr(C)]
1821
pub enum MxClassId {
1922
// from tyepdef enum { .. } mxClassID in
2023
// $MATLABROOT/extern/include/matrix.h:262 of MATLAB R2016b
21-
Unknown, Cell, Struct, Logical, Char, Void, Double, Single,
22-
Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64,
23-
Function, Opaque, Object, Index, Sparse
24+
Unknown,
25+
Cell,
26+
Struct,
27+
Logical,
28+
Char,
29+
Void,
30+
Double,
31+
Single,
32+
Int8,
33+
Uint8,
34+
Int16,
35+
Uint16,
36+
Int32,
37+
Uint32,
38+
Int64,
39+
Uint64,
40+
Function,
41+
Opaque,
42+
Object,
43+
Index,
44+
Sparse,
2445
}
2546

2647
#[cfg_attr(target_os = "linux", link(name = "mx", kind = "dylib"))]
2748
#[cfg_attr(target_os = "macos", link(name = "mx", kind = "dylib"))]
2849
#[cfg_attr(target_os = "windows", link(name = "libmx", kind = "dylib"))]
29-
extern {
50+
extern "C" {
3051
// creation
3152
#[link_name = "mxCreateNumericArray_730"]
3253
pub fn mxCreateNumericArray(
3354
ndim: size_t,
3455
dims: *const size_t,
3556
class_id: c_int,
36-
complex_flag: c_int
57+
complex_flag: c_int,
3758
) -> MxArrayMut;
3859
pub fn mxMalloc(n: MwSize) -> *mut c_void;
3960

@@ -59,6 +80,6 @@ extern {
5980
#[cfg_attr(target_os = "linux", link(name = "mex", kind = "dylib"))]
6081
#[cfg_attr(target_os = "macos", link(name = "mex", kind = "dylib"))]
6182
#[cfg_attr(target_os = "windows", link(name = "libmex", kind = "dylib"))]
62-
extern {
83+
extern "C" {
6384
pub fn mexErrMsgTxt(errormsg: *const c_uchar);
6485
}

matlab/wkwBuild.m

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ function wkwBuild()
2020
% make link paths available for cargo
2121
exportExtraLinkPaths(extraLinkPaths);
2222

23-
buildWithCargo('wkw_compress', 'wkwCompress');
24-
buildWithCargo('wkw_init', 'wkwInit');
23+
%buildWithCargo('wkw_compress', 'wkwCompress');
24+
%buildWithCargo('wkw_init', 'wkwInit');
2525
buildWithCargo('wkw_load', 'wkwLoadRoi');
26-
buildWithCargo('wkw_save', 'wkwSaveRoi');
26+
%buildWithCargo('wkw_save', 'wkwSaveRoi');
2727
end
2828

2929
function buildWithCargo(oldName, newName)
@@ -35,14 +35,14 @@ function buildWithCargo(oldName, newName)
3535

3636
% build project
3737
cd(cargoDir);
38-
system('cargo clean');
39-
system('cargo update');
38+
%system('cargo clean');
39+
%system('cargo update');
4040

4141
if ismac
4242
% In case the binary is build on arm64 make sure to use x86 as the
4343
% target.
44-
system('cargo build --release --target=x86_64-apple-darwin');
45-
libDir = fullfile(cargoDir, 'target', 'x86_64-apple-darwin', 'release');
44+
system('cargo build --release --target=aarch64-apple-darwin');
45+
libDir = fullfile(cargoDir, 'target', 'aarch64-apple-darwin', 'release');
4646
else
4747
system('cargo build --release');
4848
libDir = fullfile(cargoDir, 'target', 'release');

0 commit comments

Comments
 (0)