gaara 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gaara-0.1.0/.gitignore +69 -0
- gaara-0.1.0/LICENSE +28 -0
- gaara-0.1.0/PKG-INFO +23 -0
- gaara-0.1.0/README.md +29 -0
- gaara-0.1.0/gaara/__init__.py +49 -0
- gaara-0.1.0/gaara/fastgaara.cpp +72 -0
- gaara-0.1.0/libcrackle/LICENSE +29 -0
- gaara-0.1.0/libcrackle/builtins.hpp +50 -0
- gaara-0.1.0/libcrackle/cc3d.hpp +406 -0
- gaara-0.1.0/libcrackle/crackcodes.hpp +881 -0
- gaara-0.1.0/libcrackle/crackle.hpp +1134 -0
- gaara-0.1.0/libcrackle/crc.hpp +63 -0
- gaara-0.1.0/libcrackle/crc32c_arm.h +133 -0
- gaara-0.1.0/libcrackle/crc32c_portable.h +221 -0
- gaara-0.1.0/libcrackle/crc32c_portable.hpp +221 -0
- gaara-0.1.0/libcrackle/crc32c_x86_64_sse.h +168 -0
- gaara-0.1.0/libcrackle/dual_graph.hpp +280 -0
- gaara-0.1.0/libcrackle/header.hpp +314 -0
- gaara-0.1.0/libcrackle/labels.hpp +653 -0
- gaara-0.1.0/libcrackle/lib.hpp +261 -0
- gaara-0.1.0/libcrackle/markov.hpp +493 -0
- gaara-0.1.0/libcrackle/operations.hpp +1357 -0
- gaara-0.1.0/libcrackle/pairing_heap.hpp +348 -0
- gaara-0.1.0/libcrackle/pins.hpp +408 -0
- gaara-0.1.0/libcrackle/robin_hood.hpp +2546 -0
- gaara-0.1.0/libcrackle/threadpool.hpp +136 -0
- gaara-0.1.0/lookup_tables/Makefile +18 -0
- gaara-0.1.0/lookup_tables/README.md +65 -0
- gaara-0.1.0/lookup_tables/src/cc3d.hpp +1493 -0
- gaara-0.1.0/lookup_tables/src/isthmus.cpp +161 -0
- gaara-0.1.0/lookup_tables/src/simple.cpp +232 -0
- gaara-0.1.0/lookup_tables/tables/isthmus.bin +0 -0
- gaara-0.1.0/lookup_tables/tables/simple.bin +0 -0
- gaara-0.1.0/meson.build +39 -0
- gaara-0.1.0/pyproject.toml +31 -0
- gaara-0.1.0/src/def.hpp +145 -0
- gaara-0.1.0/src/gaara_binary.hpp +535 -0
- gaara-0.1.0/src/gaara_multilabel.hpp +537 -0
- gaara-0.1.0/src/gaara_test.cpp +232 -0
gaara-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Prerequisites
|
|
2
|
+
*.d
|
|
3
|
+
|
|
4
|
+
# Compiled Object files
|
|
5
|
+
*.slo
|
|
6
|
+
*.lo
|
|
7
|
+
*.o
|
|
8
|
+
*.obj
|
|
9
|
+
|
|
10
|
+
# Precompiled Headers
|
|
11
|
+
*.gch
|
|
12
|
+
*.pch
|
|
13
|
+
|
|
14
|
+
# Linker files
|
|
15
|
+
*.ilk
|
|
16
|
+
|
|
17
|
+
# Debugger Files
|
|
18
|
+
*.pdb
|
|
19
|
+
|
|
20
|
+
# Compiled Dynamic libraries
|
|
21
|
+
*.so
|
|
22
|
+
*.dylib
|
|
23
|
+
*.dll
|
|
24
|
+
*.so.*
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Fortran module files
|
|
28
|
+
*.mod
|
|
29
|
+
*.smod
|
|
30
|
+
|
|
31
|
+
# Compiled Static libraries
|
|
32
|
+
*.lai
|
|
33
|
+
*.la
|
|
34
|
+
*.a
|
|
35
|
+
*.lib
|
|
36
|
+
|
|
37
|
+
# Executables
|
|
38
|
+
*.exe
|
|
39
|
+
*.out
|
|
40
|
+
*.app
|
|
41
|
+
|
|
42
|
+
# Build directories
|
|
43
|
+
build/
|
|
44
|
+
Build/
|
|
45
|
+
build-*/
|
|
46
|
+
|
|
47
|
+
# CMake generated files
|
|
48
|
+
CMakeFiles/
|
|
49
|
+
CMakeCache.txt
|
|
50
|
+
cmake_install.cmake
|
|
51
|
+
Makefile
|
|
52
|
+
install_manifest.txt
|
|
53
|
+
compile_commands.json
|
|
54
|
+
|
|
55
|
+
# Temporary files
|
|
56
|
+
*.tmp
|
|
57
|
+
*.log
|
|
58
|
+
*.bak
|
|
59
|
+
*.swp
|
|
60
|
+
|
|
61
|
+
# vcpkg
|
|
62
|
+
vcpkg_installed/
|
|
63
|
+
|
|
64
|
+
# debug information files
|
|
65
|
+
*.dwo
|
|
66
|
+
|
|
67
|
+
# test output & cache
|
|
68
|
+
Testing/
|
|
69
|
+
.cache/
|
gaara-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, William Silversmith
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
gaara-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gaara
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Skeleton generation via 3D voxel thinning.
|
|
5
|
+
License-Expression: BSD-3-Clause
|
|
6
|
+
Classifier: Intended Audience :: Developers
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Programming Language :: Python
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Operating System :: POSIX
|
|
18
|
+
Classifier: Operating System :: MacOS
|
|
19
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: numpy
|
|
23
|
+
|
gaara-0.1.0/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# gaara
|
|
2
|
+
Skeleton thinning algorithm for large images.
|
|
3
|
+
|
|
4
|
+
```python
|
|
5
|
+
import gaara
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
arr = np.load(...) # some 3d array in fortran order
|
|
9
|
+
|
|
10
|
+
# binary images are slightly more efficient to process
|
|
11
|
+
# 80% of the memory and slightly faster.
|
|
12
|
+
|
|
13
|
+
arr = gaara.skeletonize(arr, binary_image=True, in_place=False)
|
|
14
|
+
arr = gaara.skeletonize(arr, binary_image=False, in_place=False)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Gaara is a skeletion generation via voxel thinning algorithm based on Palágyi's 2014 paper [1] and inspired by Matejek et al.'s work on [synapseaware](https://github.com/Rhoana/synapseaware/). [2]
|
|
18
|
+
|
|
19
|
+
While efficient and fine for tracing neurites that have a natural tree structure, a shortcoming of [Kimimaro](https://github.com/seung-lab/kimimaro) is its inability to generate topologically correct skeletons [3] which have applications to e.g. glia and blood vessels.
|
|
20
|
+
|
|
21
|
+
Gaara attempts to be an efficient voxel thinning algorithm implementation that can handle very large images on a single machine by making use of crackle compression dynamically.
|
|
22
|
+
|
|
23
|
+
## References
|
|
24
|
+
|
|
25
|
+
1. K. Palágyi et al., “A Sequential 3D Thinning Algorithm and Its Medical Applications,” in Information Processing in Medical Imaging, M. F. Insana and R. M. Leahy, Eds., Berlin, Heidelberg: Springer, 2001, pp. 409–415. doi: 10.1007/3-540-45729-1_42.
|
|
26
|
+
|
|
27
|
+
2. B. Matejek, D. Wei, X. Wang, J. Zhao, K. Palágyi, and H. Pfister, “Synapse-Aware Skeleton Generation for Neural Circuits,” in Medical Image Computing and Computer Assisted Intervention – MICCAI 2019, D. Shen, T. Liu, T. M. Peters, L. H. Staib, C. Essert, S. Zhou, P.-T. Yap, and A. Khan, Eds., Cham: Springer International Publishing, 2019, pp. 227–235. doi: 10.1007/978-3-030-32239-7_26.
|
|
28
|
+
|
|
29
|
+
3. T. A. Syed, M. Youssef, A. L. Schober, Y. Kubota, K. K. Murai, and C. K. Salmon, “Beyond Neurons: Computer Vision Methods for Analysis of Morphologically Complex Astrocytes,” Frontiers in Computer Science, vol. 6, Sep. 2024, doi: 10.3389/fcomp.2024.1156204.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy.typing as npt
|
|
3
|
+
|
|
4
|
+
from . import fastgaara
|
|
5
|
+
|
|
6
|
+
__all__ = ["skeletonize"]
|
|
7
|
+
|
|
8
|
+
def skeletonize(
|
|
9
|
+
labels:npt.NDArray[np.integer],
|
|
10
|
+
binary_image:bool = False,
|
|
11
|
+
in_place:bool = False
|
|
12
|
+
) -> npt.NDArray[np.integer]:
|
|
13
|
+
"""
|
|
14
|
+
Apply Palagyi's 3D voxel thinning algorithm to `labels`, a binary image.
|
|
15
|
+
|
|
16
|
+
Reference:
|
|
17
|
+
|
|
18
|
+
K. Palágyi, "A Sequential 3D Curve-Thinning Algorithm Based on Isthmuses,"
|
|
19
|
+
in Advances in Visual Computing, vol. 8888,
|
|
20
|
+
G. Bebis, R. Boyle, B. Parvin, D. Koracin, R. McMahan, J. Jerald,
|
|
21
|
+
H. Zhang, S. M. Drucker, C. Kambhamettu, M. El Choubassi, Z. Deng,
|
|
22
|
+
and M. Carlson, Eds.,
|
|
23
|
+
Cham: Springer International Publishing, 2014, pp. 406–415.
|
|
24
|
+
doi: 10.1007/978-3-319-14364-4_39.
|
|
25
|
+
"""
|
|
26
|
+
if labels.ndim != 3:
|
|
27
|
+
raise ValueError(f"This function only supports 3D images. Got: {labels.shape}")
|
|
28
|
+
|
|
29
|
+
if labels.size <= 1:
|
|
30
|
+
return labels
|
|
31
|
+
|
|
32
|
+
if in_place and not labels.flags.f_contiguous:
|
|
33
|
+
raise ValueError("Cannot perform an in-place operation on non-Fortran ordered data.")
|
|
34
|
+
elif not in_place:
|
|
35
|
+
labels = np.copy(labels, order="F")
|
|
36
|
+
|
|
37
|
+
orig_dtype = labels.dtype
|
|
38
|
+
if labels.dtype == bool:
|
|
39
|
+
binary_image = True
|
|
40
|
+
labels = labels.view(np.uint8)
|
|
41
|
+
|
|
42
|
+
if binary_image:
|
|
43
|
+
fastgaara.thin_palagyi_binary(labels)
|
|
44
|
+
else:
|
|
45
|
+
fastgaara.thin_palagyi_multilabel(labels)
|
|
46
|
+
|
|
47
|
+
return labels.view(orig_dtype)
|
|
48
|
+
|
|
49
|
+
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#define PYBIND11_DETAILED_ERROR_MESSAGES
|
|
2
|
+
|
|
3
|
+
#include <pybind11/pybind11.h>
|
|
4
|
+
#include <pybind11/numpy.h>
|
|
5
|
+
#include <pybind11/stl.h>
|
|
6
|
+
|
|
7
|
+
#include <cstdlib>
|
|
8
|
+
#include <cmath>
|
|
9
|
+
|
|
10
|
+
#include "gaara_binary.hpp"
|
|
11
|
+
#include "gaara_multilabel.hpp"
|
|
12
|
+
|
|
13
|
+
namespace py = pybind11;
|
|
14
|
+
|
|
15
|
+
template <typename Func>
|
|
16
|
+
void dispatch_skeletonize(const py::array& labels, Func&& func) {
|
|
17
|
+
py::dtype dt = labels.dtype();
|
|
18
|
+
const int width = dt.itemsize();
|
|
19
|
+
|
|
20
|
+
const uint64_t sx = labels.shape()[0];
|
|
21
|
+
const uint64_t sy = labels.shape()[1];
|
|
22
|
+
const uint64_t sz = labels.ndim() > 2
|
|
23
|
+
? labels.shape()[2]
|
|
24
|
+
: 1;
|
|
25
|
+
|
|
26
|
+
void* data = const_cast<void*>(labels.data());
|
|
27
|
+
|
|
28
|
+
if (width == 1) {
|
|
29
|
+
func(static_cast<uint8_t*>(data), sx, sy, sz);
|
|
30
|
+
}
|
|
31
|
+
else if (width == 2) {
|
|
32
|
+
func(static_cast<uint16_t*>(data), sx, sy, sz);
|
|
33
|
+
}
|
|
34
|
+
else if (width == 4) {
|
|
35
|
+
func(static_cast<uint32_t*>(data), sx, sy, sz);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
func(static_cast<uint64_t*>(data), sx, sy, sz);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// assumes fortran order
|
|
43
|
+
py::array thin_palagyi_binary(const py::array& labels) {
|
|
44
|
+
dispatch_skeletonize(labels, [](auto *data, uint64_t sx, uint64_t sy, uint64_t sz) {
|
|
45
|
+
using T = std::remove_pointer_t<decltype(data)>;
|
|
46
|
+
return gaara::binary::skeletonize<T>(
|
|
47
|
+
data,
|
|
48
|
+
sx, sy, sz
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return labels;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// assumes fortran order
|
|
56
|
+
py::array thin_palagyi_multilabel(const py::array& labels) {
|
|
57
|
+
dispatch_skeletonize(labels, [](auto *data, uint64_t sx, uint64_t sy, uint64_t sz) {
|
|
58
|
+
using T = std::remove_pointer_t<decltype(data)>;
|
|
59
|
+
return gaara::multilabel::skeletonize<T>(
|
|
60
|
+
data,
|
|
61
|
+
sx, sy, sz
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return labels;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
PYBIND11_MODULE(fastgaara, m) {
|
|
69
|
+
m.doc() = "Python interface for Gaara C++ functions.";
|
|
70
|
+
m.def("thin_palagyi_binary", &thin_palagyi_binary, "Perform morphological thinning using the Palagyi algorithm on a binary 3D image.");
|
|
71
|
+
m.def("thin_palagyi_multilabel", &thin_palagyi_multilabel, "Perform morphological thinning using the Palagyi algorithm on a binary 3D image.");
|
|
72
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022-2026 William Silversmith
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#ifndef _CRACKLE_BUILTINS_HXX_
|
|
2
|
+
#define _CRACKLE_BUILTINS_HXX_
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#ifdef _MSC_VER
|
|
6
|
+
# include <intrin.h>
|
|
7
|
+
# define popcount __popcnt
|
|
8
|
+
|
|
9
|
+
// https://stackoverflow.com/questions/355967/how-to-use-msvc-intrinsics-to-get-the-equivalent-of-this-gcc-code
|
|
10
|
+
unsigned long ctz(unsigned long value) {
|
|
11
|
+
unsigned long trailing_zero = 0;
|
|
12
|
+
if (_BitScanForward(&trailing_zero, value)) {
|
|
13
|
+
return trailing_zero;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return 32;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
#else
|
|
20
|
+
# define popcount __builtin_popcount
|
|
21
|
+
# define ctz __builtin_ctz
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
uint32_t ffs (uint32_t x) {
|
|
25
|
+
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
|
|
26
|
+
return __builtin_ffs(x);
|
|
27
|
+
#elif defined _MSC_VER
|
|
28
|
+
/* _BitScanForward
|
|
29
|
+
<https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64> */
|
|
30
|
+
unsigned long bit;
|
|
31
|
+
if (_BitScanForward (&bit, x)) {
|
|
32
|
+
return bit + 1;
|
|
33
|
+
}
|
|
34
|
+
return 0;
|
|
35
|
+
#else
|
|
36
|
+
if (x == 0) {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
constexpr uint32_t num_bits = sizeof(x) * 8;
|
|
40
|
+
for (uint32_t i = 0; i < num_bits; i++) {
|
|
41
|
+
if ((x >> i) & 0x1) {
|
|
42
|
+
return i + 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return 0;
|
|
46
|
+
#endif
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
#endif
|