Skip to main content

PyPI version

Kimimaro: Skeletonize Densely Labeled Images

# Produce SWC files from volumetric images.
kimimaro forge labels.npy --progress # writes to ./kimimaro_out/
kimimaro view kimimaro_out/10.swc

Rapidly skeletonize all non-zero labels in 2D and 3D numpy arrays using a TEASAR derived method. The returned list of skeletons is in the format used by cloud-volume. A skeleton is a stick figure 1D representation of a 2D or 3D object that consists of a graph of verticies linked by edges. A skeleton where the verticies also carry a distance to the nearest boundary they were extracted from is called a "Medial Axis Transform", which Kimimaro provides.

Skeletons are a compact representation that can be used to visualize objects, trace the connectivity of an object, or otherwise analyze the object's geometry. Kimimaro was designed for use with high resolution neurons extracted from electron microscopy data via AI segmentation, but it can be applied to many different fields.

On an Apple Silicon M1 arm64 chip (Firestorm cores 3.2 GHz max frequency), this package processed a 512x512x100 volume with 333 labels in 20 seconds. It processed a 512x512x512 volume (connectomics.npy) with 2124 labels in 187 seconds.

A Densely Labeled Volume Skeletonized with Kimimaro
Fig. 1: A Densely Labeled Volume Skeletonized with Kimimaro

pip Installation

If a binary is available for your platform:

pip install kimimaro 
# installs additional libraries to accelerate some
# operations like join_close_components
pip install "kimimaro[accel]"
# Makes the kimimaro view command work
pip install "kimimaro[view]"
# Enables TIFF generation on the CLI
pip install "kimimaro[tif]"
# Enables reading NIBABEL, NRRD, TIFF, CRACKLE on the CLI
pip install "kimimaro[all_formats]"
# Install all optional dependencies
pip install "kimimaro[all]"

Otherwise, you'll also need a C++ compiler:

sudo apt-get install python3-dev g++ # ubuntu linux

Example

A Densely Labeled Volume Skeletonized with Kimimaro
Fig. 2: Memory Usage on a 512x512x512 Densely Labeled Volume (`connectomics.npy`)

Figure 2 shows the memory usage and processessing time (~390 seconds, about 6.5 minutes) required when Kimimaro 1.4.0 was applied to a 512x512x512 cutout, labels, from a connectomics dataset, connectomics.npy containing 2124 connected components. The different sections of the algorithm are depicted. Grossly, the preamble runs for about half a minute, skeletonization for about six minutes, and finalization within seconds. The peak memory usage was about 4.5 GB. The code below was used to process labels. The processing of the glia was truncated in due to a combination of fix_borders and max_paths.

Kimimaro has come a long way. Version 0.2.1 took over 15 minutes and had a Preamble run time twice as long on the same dataset.

On a Macbook Pro M3, the same settings now complete in 94 seconds (1.6 minutes) on version 5.4.0. With xs3d 1.11.0, cross section analysis takes 215 seconds (3.6 minutes).

Python Interface

# LISTING 1: Producing Skeletons from a labeled image.

import kimimaro

# To obtain this 512 MB segmentation sample volume:
# pip install crackle-codec 

import crackle
labels = crackle.load("benchmarks/connectomics.npy.ckl.gz") 

skels = kimimaro.skeletonize(
  labels, 
  teasar_params={
    "scale": 1.5, 
    "const": 300, # physical units
    "pdrf_scale": 100000,
    "pdrf_exponent": 4,
    "soma_acceptance_threshold": 3500, # physical units
    "soma_detection_threshold": 750, # physical units
    "soma_invalidation_const": 300, # physical units
    "soma_invalidation_scale": 2,
    "max_paths": 300, # default None
  },
  # object_ids=[ ... ], # process only the specified labels
  # extra_targets_before=[ (27,33,100), (44,45,46) ], # target points in voxels
  # extra_targets_after=[ (27,33,100), (44,45,46) ], # target points in voxels
  dust_threshold=1000, # skip connected components with fewer than this many voxels
  anisotropy=(16,16,40), # default True
  fix_branching=True, # default True
  fix_borders=True, # default True
  fill_holes=False, # default False
  fix_avocados=False, # default False
  progress=True, # default False, show progress bar
  parallel=1, # <= 0 all cpu, 1 single process, 2+ multiprocess
  parallel_chunk_size=100, # how many skeletons to process before updating progress bar
)

# LISTING 2: Combining skeletons produced from 
#            adjacent or overlapping images.

import kimimaro
from osteoid import Skeleton

skels = ... # a set of skeletons produced from the same label id
skel = Skeleton.simple_merge(skels).consolidate()
skel = kimimaro.postprocess(
  skel, 
  dust_threshold=1000, # physical units
  tick_threshold=3500 # physical units
)

# LISTING 3: Adding cross sectional area to skeletons
# Cross section planes are defined by normal vectors. Those
# vectors come from the difference between adjacent vertices.
skels = ... # one or more skeletons produced from a single image
skels = kimimaro.cross_sectional_area(
  labels, skels, 
  anisotropy=(16,16,40), 
  smoothing_window=5, # rolling average window of plane normals
  progress=True,
)
skel = skels[0]
skel.cross_sectional_area # array of cross sectional areas
skel.cross_sectional_area_contacts # non-zero contacted the image border

# Split input skeletons into connected components and
# then join the two nearest vertices within `radius` distance
# of each other until there is only a single connected component
# or no pairs of points nearer than `radius` exist. 
# Fuse all remaining components into a single skeleton.
skel = kimimaro.join_close_components([skel1, skel2], radius=1500) # 1500 units threshold
skel = kimimaro.join_close_components([skel1, skel2], radius=None) # no threshold

# Given synapse centroids (in voxels) and the SWC integer label you'd 
# like to assign (e.g. for pre-synaptic and post-synaptic) this finds the 
# nearest voxel to the centroid for that label.
# Input: { label: [ ((x,y,z), swc_label), ... ] }
# Returns: { (x,y,z): swc_label, ... }
extra_targets = kimimaro.synapses_to_targets(labels, synapses)


# LISTING 4: Drawing a centerline between
#   preselected points on a binary image.
#   This is a much simpler option for when
#   you know exactly what you want, but may
#   be less efficient for large scale procesing.

skel = kimimaro.connect_points(
  labels == 67301298,
  start=(3, 215, 202), 
  end=(121, 426, 227),
  anisotropy=(32,32,40),
)

# LISTING 5: Using skeletons to oversegment existing
#  segmentations for integration into proofreading systems 
#  that on merging atomic labels. oversegmented_labels 
#  is returned numbered from 1. skels is a copy returned 
#  with the property skel.segments that associates a label
#  to each vertex (labels will not be unique if downsampling 
#  is used)
oversegmented_labels, skels = kimimaro.oversegment(
  labels, skels, 
  anisotropy=(32,32,40), 
  downsample=10,
)

connectomics.npy is multilabel connectomics data derived from pinky40, a 2018 experimental automated segmentation of ~1.5 million cubic micrometers of mouse visual cortex. It is an early predecessor to the now public pinky100_v185 segmentation that can be found at https://microns-explorer.org/phase1 You will need to run lzma -d connectomics.npy.lzma to obtain the 512x512x512 uint32 volume at 32x32x40 nm3 resolution.

CLI Interface

The CLI supports producing skeletons from a single image as SWCs and viewing the resulting SWC files one at a time. By default, the SWC files are written to ./kimimaro_out/$LABEL.swc.

Here's an equivalent example to the code above.

kimimaro forge labels.npy --scale 4 --const 10 --soma-detect 1100 --soma-accept 3500 --soma-scale 1 --soma-const 300 --anisotropy 16,16,40 --fix-borders --progress 

Visualize the your data:

kimimaro view 1241241.swc # visualize skeleton
kimimaro view labels.npy # visualize segmentation

It can also convert binary image skeletons produced by thinning algorithms into SWC files and back. This can be helpful for comparing different skeletonization algorithms or even just using their results.

kimimaro swc from binary_image.tiff # -> binary_image.swc
kimimaro swc to --format tiff binary_image.swc # -> binary_image.tiff or npy

Tweaking kimimaro.skeletonize Parameters

This algorithm works by finding a root point on a 3D object and then serially tracing paths via dijksta's shortest path algorithm through a penalty field to the most distant unvisited point. After each pass, there is a sphere (really a circumscribing cube) that expands around each vertex in the current path that marks part of the object as visited.

For a visual tutorial on the basics of the skeletonization procedure, check out this wiki article: A Pictorial Guide to TEASAR Skeletonization

For more detailed information, read below or the TEASAR paper (though we deviate from TEASAR in a few places). [1]

scale and const

Usually, the most important parameters to tweak are scale and const which control the radius of this invalidation sphere according to the equation r(x,y,z) = scale * DBF(x,y,z) + const where the dimensions are physical (e.g. nanometers, i.e. corrected for anisotropy). DBF(x,y,z) is the physical distance from the shape boundary at that point.

Check out this wiki article to help refine your intuition.

anisotropy

Represents the physical dimension of each voxel. For example, a connectomics dataset might be scanned with an electron microscope at 4nm x 4nm per pixel and stacked in slices 40nm thick. i.e. anisotropy=(4,4,40). You can use any units so long as you are consistent.

dust_threshold

This threshold culls connected components that are smaller than this many voxels.

extra_targets_after and extra_targets_before

extra_targets_after provides additional voxel targets to trace to after the morphological tracing algorithm completes. For example, you might add known synapse locations to the skeleton.

extra_targets_before is the same as extra_targets_after except that the additional targets are front-loaded and the paths that they cover are invalidated. This may affect the results of subsequent morphological tracing.

max_paths

Limits the number of paths that can be drawn for the given label. Certain cells, such as glia, that may not be important for the current analysis may be expensive to process and can be aborted early.

pdrf_scale and pdrf_exponent

The pdrf_scale and pdrf_exponent represent parameters to the penalty equation that takes the euclidean distance field (D) and augments it so that cutting closer to the border is very penalized to make dijkstra take paths that are more centered.

Pr = pdrf_scale * (1 - D / max(D)) pdrf_exponent + (directional gradient < 1.0).

The default settings should work fairly well, but under large anisotropies or with cavernous morphologies, it's possible that you might need to tweak it. If you see the skeleton go haywire inside a large area, it could be a collapse of floating point precision.

soma_acceptance_threshold and soma_detection_threshold

We process somas specially because they do not have a tubular geometry and instead should be represented in a hub and spoke manner. soma_acceptance_threshold is the physical radius (e.g. in nanometers) beyond which we classify a connected component of the image as containing a soma. The distance transform's output is depressed by holes in the label, which are frequently produced by segmentation algorithms on somata. We can fill them, but the hole filling algorithm we use is slow so we would like to only apply it occasionally. Therefore, we set a lower threshold, the soma_acceptance_threshold, beyond which we fill the holes and retest the soma.

soma_invalidation_scale and soma_invalidation_const

Once we have classified a region as a soma, we fix root of the skeletonization algorithm at one of the points of maximum distance from the boundary (usually there is only one). We then mark as visited all voxels around that point in a spherical radius described by r(x,y,z) = soma_invalidation_scale * DBF(x,y,z) + soma_invalidation_const where DBF(x,y,z) is the physical distance from the shape boundary at that point. If done correctly, this can prevent skeletons from being drawn to the boundaries of the soma, and instead pulls the skeletons mainly into the processes extending from the cell body.

fix_borders

This feature makes it easier to connect the skeletons of adjacent image volumes that do not fit in RAM. If enabled, skeletons will be deterministically drawn to the approximate center of the 2D contact area of each place where the shape contacts the border. This can affect the performance of the operation positively or negatively depending on the shape and number of contacts.

fix_branching

You'll probably never want to disable this, but base TEASAR is infamous for forking the skeleton at branch points way too early. This option makes it preferential to fork at a more reasonable place at a significant performance penalty.

fill_holes

Warning: This will remove input labels that are deemed to be holes.

If your segmentation contains artifacts that cause holes to appear in labels, you can preprocess the entire image to eliminate background holes and holes caused by entirely contained inclusions. This option adds a moderate amount of additional processing time at the beginning (perhaps ~30%).

fix_avocados

Avocados are segmentations of cell somata that classify the nucleus separately from the cytoplasm. This is a common problem in automatic segmentations due to the visual similarity of a cell membrane and a nuclear membrane combined with insufficient context.

Skeletonizing an avocado results in a poor skeletonization of the cell soma that will disconnect the nucleus and usually results in too many paths traced around the nucleus. Setting fix_avocados=True attempts to detect and fix these problems. Currently we handle non-avocados, avocados, cells with inclusions, and nested avocados. You can see examples here.

progress

Show a progress bar once the skeletonization phase begins.

parallel

Use a pool of processors to skeletonize faster. Each process allocatable task is the skeletonization of one connected component (so it won't help with a single label that takes a long time to skeletonize). This option also affects the speed of the initial euclidean distance transform, which is parallel enabled and is the most expensive part of the Preamble (described below).

parallel_chunk_size

This only applies when using parallel. This sets the number of skeletons a subprocess will extract before returning control to the main thread, updating the progress bar, and acquiring a new task. If this value is set too low (e.g. < 10-20) the cost of interprocess communication can become significant and even dominant. If it is set too high, task starvation may occur for the other subprocesses if a subprocess gets a particularly hard skeleton and they complete quickly. Progress bar updates will be infrequent if the value is too high as well.

The actual chunk size used will be min(parallel_chunk_size, len(cc_labels) // parallel). cc_labels represents the number of connected components in the sample.

Performance Tips

  • If you only need a few labels skeletonized, pass in object_ids to bypass processing all the others. If object_ids contains only a single label, the masking operation will run faster.
  • Larger TEASAR parameters scale and const require processing larger invalidation regions per path.
  • Set pdrf_exponent to a small power of two (e.g. 1, 2, 4, 8, 16) for a small speedup.
  • If you are willing to sacrifice the improved branching behavior, you can set fix_branching=False for a moderate 1.1x to 1.5x speedup (assuming your TEASAR parameters and data allow branching).
  • If your dataset contains important cells (that may in fact be the seat of consciousness) but they take significant processing power to analyze, you can save them to savor for later by setting max_paths to some reasonable level which will abort and proceed to the next label after the algorithm detects that that at least that many paths will be needed.
  • Parallel distributes work across connected components and is generally a good idea if you have the cores and memory. Not only does it make single runs proceed faster, but you can also practically use a much larger context; that improves soma processing as they are less likely to be cut off. The Preamble of the algorithm (detailed below) is still single threaded at the moment, so task latency increases with size.
  • If parallel_chunk_size is set very low (e.g. < 10) during parallel operation, interprocess communication can become a significant overhead. Try raising this value.

Motivation

The connectomics field commonly generates very large densely labeled volumes of neural tissue. Skeletons are one dimensional representations of two or three dimensional objects. They have many uses, a few of which are visualization of neurons, calculating global topological features, rapidly measuring electrical distances between objects, and imposing tree structures on neurons (useful for computation and user interfaces). There are several ways to compute skeletons and a few ways to define them [4]. After some experimentation, we found that the TEASAR [1] approach gave fairly good results. Other approaches include topological thinning ("onion peeling") and finding the centerline described by maximally inscribed spheres. Ignacio Arganda-Carreras, an alumnus of the Seung Lab, wrote a topological thinning plugin for Fiji called Skeletonize3d.

There are several implementations of TEASAR used in the connectomics field [3][5], however it is commonly understood that implementations of TEASAR are slow and can use tens of gigabytes of memory. Our goal to skeletonize all labels in a petavoxel scale image quickly showed clear that existing sparse implementations are impractical. While adapting a sparse approach to a cloud pipeline, we noticed that there are inefficiencies in repeated evaluation of the Euclidean Distance Transform (EDT), the repeated evaluation of the connected components algorithm, in the construction of the graph used by Dijkstra's algorithm where the edges are implied by the spatial relationships between voxels, in the memory cost, quadratic in the number of voxels, of representing a graph that is implicit in image, in the unnecessarily large data type used to represent relatively small cutouts, and in the repeated downloading of overlapping regions. We also found that the naive implmentation of TEASAR's "rolling invalidation ball" unnecessarily reevaluated large numbers of voxels in a way that could be loosely characterized as quadratic in the skeleton path length.

We further found that commodity implementations of the EDT supported only binary images. We were unable to find any available Python or C++ libraries for performing Dijkstra's shortest path on an image. Commodity implementations of connected components algorithms for images supported only binary images. Therefore, several libraries were devised to remedy these deficits (see Related Projects).

Why TEASAR?

TEASAR: Tree-structure Extraction Algorithm for Accurate and Robust skeletons, a 2000 paper by M. Sato and others [1], is a member of a family of algorithms that transform two and three dimensional structures into a one dimensional "skeleton" embedded in that higher dimension. One might concieve of a skeleton as extracting a stick figure drawing from a binary image. This problem is more difficult than it might seem. There are different situations one must consider when making such a drawing. For example, a stick drawing of a banana might merely be a curved centerline and a drawing of a doughnut might be a closed loop. In our case of analyzing neurons, sometimes we want the skeleton to include spines, short protrusions from dendrites that usually have synapses attached, and sometimes we want only the characterize the run length of the main trunk of a neurite.

Additionally, data quality issues can be challenging as well. If one is skeletonizing a 2D image of a doughnut, but the angle were sufficiently declinated from the ring's orthogonal axis, would it even be possible to perform this task accurately? In a 3D case, if there are breaks or mergers in the labeling of a neuron, will the algorithm function sensibly? These issues are common in both manual and automatic image sementations.

In our problem domain of skeletonizing neurons from anisotropic voxel labels, our chosen algorithm should produce tree structures, handle fine or coarse detail extraction depending on the circumstances, handle voxel anisotropy, and be reasonably efficient in CPU and memory usage. TEASAR fufills these criteria. Notably, TEASAR doesn't guarantee the centeredness of the skeleton within the shape, but it makes an effort. The basic TEASAR algorithm is known to cut corners around turns and branch too early. A 2001 paper by members of the original TEASAR team describes a method for reducing the early branching issue on page 204, section 4.2.2. [2]

TEASAR Derived Algorithm

We implemented TEASAR but made several deviations from the published algorithm in order to improve path centeredness, increase performance, handle bulging cell somas, and enable efficient chunked evaluation of large images. We opted not to implement the gradient vector field step from [2] as our implementation is already quite fast. The paper claims a reduction of 70-85% in input voxels, so it might be worth investigating.

In order to work with images that contain many labels, our general strategy is to perform as many actions as possible in such a way that all labels are treated in a single pass. Several of the component algorithms (e.g. connected components, euclidean distance transform) in our implementation can take several seconds per a pass, so it is important that they not be run hundreds or thousands of times. A large part of the engineering contribution of this package lies in the efficiency of these operations which reduce the runtime from the scale of hours to minutes.

Given a 3D labeled voxel array, I, with N >= 0 labels, and ordered triple describing voxel anisotropy A, our algorithm can be divided into three phases, the pramble, skeletonization, and finalization in that order.

I. Preamble

The Preamble takes a 3D image containing N labels and efficiently generates the connected components, distance transform, and bounding boxes needed by the skeletonization phase.

  1. To enhance performance, if N is 0 return an empty set of skeletons.
  2. Label the M connected components, Icc, of I.
  3. To save memory, renumber the connected components in order from 1 to M. Adjust the data type of the new image to the smallest uint type that will contain M and overwrite Icc.
  4. Generate a mapping of the renumbered Icc to I to assign meaningful labels to skeletons later on and delete I to save memory.
  5. Compute E, the multi-label anisotropic Euclidean Distance Transform of Icc given A. E treats all interlabel edges as transform edges, but not the boundaries of the image. Black pixels are considered background.
  6. Gather a list, Lcc of unique labels from Icc and threshold which ones to process based on the number of voxels they represent to remove "dust".
  7. In one pass, compute the list of bounding boxes, B, corresponding to each label in Lcc.

II. Skeletonization

In this phase, we extract the tree structured skeleton from each connected component label. Below, we reference variables defined in the Preamble. For clarity, we omit the soma specific processing and hold fix_branching=True.

For each label l in Lcc and B...

  1. Extract Il, the cropped binary image tightly enclosing l from Icc using Bl
  2. Using Il and Bl, extract El from E. El is the cropped tightly enclosed EDT of l. This is much faster than recomputing the EDT for each binary image.
  3. Find an arbitrary foreground voxel and using that point as a source, compute the anisotropic euclidean distance field for Il. The coordinate of the maximum value is now "the root" r.
  4. From r, compute the euclidean distance field and save it as the distance from root field Dr.
  5. Compute the penalized distance from root field Pr = pdrf_scale * ((1 - El / max(El)) ^ pdrf_exponent) + Dr / max(Dr).
  6. While Il contains foreground voxels:
    1. Identify a target coordinate, t, as the foreground voxel with maximum distance in Dr from r.
    2. Draw the shortest path p from r to t considering the voxel values in Pr as edge weights.
    3. For each vertex v in p, extend an invalidation cube of physical side length computed as scale * El(v) + const and convert any foreground pixels in Il that overlap with these cubes to background pixels.
    4. (Only if fix_branching=True) For each vertex coordinate v in p, set Pr(v) = 0.
    5. Append p to a list of paths for this label.
  7. Using El, extract the distance to the nearest boundary each vertex in the skeleton represents.
  8. For each raw skeleton extracted from Il, translate the vertices by Bl to correct for the translation the cropping operation induced.
  9. Multiply the vertices by the anisotropy A to place them in physical space.

If soma processing is considered, we modify the root (r) search process as follows:

  1. If max(El) > soma_detection_threshold...
  2. Fill toplogical holes in Il. Soma are large regions that often have dust from imperfect automatic labeling methods.
  3. Recompute El from this cleaned up image.
  4. If max(El) > soma_acceptance_threshold, divert to soma processing mode.
  5. If in soma processing mode, continue, else go to step 3 in the algorithm above.
  6. Set r to the coordinate corresponding to max(El)
  7. Create an invalidation sphere of physical radius soma_invalidation_scale * max(El) + soma_invalidation_const and erase foreground voxels from Il contained within it. This helps prevent errant paths from being drawn all over the soma.
  8. Continue from step 4 in the above algorithm.

III. Finalization

In the final phase, we agglomerate the disparate connected component skeletons into single skeletons and assign their labels corresponding to the input image. This step is artificially broken out compared to how intermingled its implementation is with skeletonization, but it's conceptually separate.

Deviations from TEASAR

There were several places where we took a different approach than called for by the TEASAR authors.

Using DAF for Targets, PDRF for Pathfinding

The original TEASAR algorithm defines the Penalized Distance from Root voxel Field (PDRF, Pr above) as:

PDRF = 5000 * (1 - DBF / max(DBF))^16 + DAF

DBF is the Distance from Boundary Field (El above) and DAF is the Distance from Any voxel Field (Dr above).

We found the addition of the DAF tended to perturb the skeleton path from the centerline better described by the inverted DBF alone. We also found it helpful to modify the constant and exponent to tune cornering behavior. Initially, we completely stripped out the addition of the DAF from the PDRF, but this introduced a different kind of problem. The exponentiation of the PDRF caused floating point values to collapse in wide open spaces. This made the skeletons go crazy as they traced out a path described by floating point errors.

The DAF provides a very helpful gradient to follow between the root and the target voxel, we just don't want that gradient to knock the path off the centerline. Therefore, in light of the fact that the PDRF base field is very large, we add the normalized DAF which is just enough to overwhelm floating point errors and provide direction in wide tubes and bulges.

The original paper also called for selecting targets using the max(PDRF) foreground values. However, this is a bit strange since the PDRF values are dominated by boundary effects rather than a pure distance metric. Therefore, we select targets from the max(DAF) forground value.

Zero Weighting Previous Paths (fix_branching=True)

The 2001 skeletonization paper [2] called for correcting early forking by computing a DAF using already computed path vertices as field sources. This allows Dijkstra's algorithm to trace the existing path cost free and diverge from it at a closer point to the target.

As we have strongly deemphasized the role of the DAF in dijkstra path finding, computing this field is unnecessary and we only need to set the PDRF to zero along the path of existing skeletons to achieve this effect. This saves us an expensive repeated DAF calculation per path.

However, we still incur a substantial cost for taking this approach because we had been computing a dijkstra "parental field" that recorded the shortest path to the root from every foreground voxel. We then used this saved result to rapidly compute all paths. However, as this zero weighting modification makes successive calculations dependent upon previous ones, we need to compute Dijkstra's algorithm anew for each path.

Non-Overlapped Chunked Processing (fix_borders=True)

When processing large volumes, a sensible approach for mass producing skeletons is to chunk the volume, process the chunks independently, and merge the resulting skeleton fragments at the end. However, this is complicated by the "edge effect" induced by a loss of context which makes it impossible to expect the endpoints of skeleton fragments produced by adjacent chunks to align. In contrast, it is easy to join mesh fragments because the vertices of the edge of mesh fragments lie at predictable identical locations given one pixel of overlap.

Previously, we had used 50% overlap to join adjacent skeleton fragments which increased the compute cost of skeletonizing a large volume by eight times. However, if we could force skeletons to lie at predictable locations on the border, we could use single pixel overlap and copy the simple mesh joining approach. As an (incorrect but useful) intuition for how one might go about this, consider computing the centroid of each connected component on each border plane and adding that as a required path target. This would guarantee that both sides of the plane connect at the same pixel. However, the centroid may not lie inside of non-convex hulls so we have to be more sophisticated and select some real point inside of the shape.

To this end, we again repurpose the euclidean distance transform and apply it to each of the six planes of connected components and select the maximum value as a mandatory target. This works well for many types of objects that contact a single plane and have a single maximum. However, we must treat the corners of the box and shapes that have multiple maxima.

To handle shapes that contact multiple sides of the box, we simply assign targets to all connected components. If this introduces a cycle in post-processing, we already have cycle removing code to handle it in Igneous. If it introduces tiny useless appendages, we also have code to handle this.

If a shape has multiple distance transform maxima, it is important to choose the same pixel without needing to communicate between spatially adjacent tasks which may run at different times on different machines. Additionally, the same plane on adjacent tasks has the coordinate system flipped. One simple approach might be to pick the coordinate with minimum x and y (or some other coordinate based criterion) in one of the coordinate frames, but this requires tracking the flips on all six planes and is annoying. Instead, we use a series of coordinate-free topology based filters which is both more fun, effort efficient, and picks something reasonable looking. A valid criticism of this approach is that it will fail on a perfectly symmetrical object, but these objects are rare in biological data.

We apply a series of filters and pick the point based on the first filter it passes:

  1. The voxel closest to the centroid of the current label.
  2. The voxel closest to the centroid of the image plane.
  3. Closest to a corner of the plane.
  4. Closest to an edge of the plane.
  5. The previously found maxima.

It is important that filter #1 be based on the shape of the label so that kinks are minimimized for convex hulls. For example, originally we used only filters two thru five, but this caused skeletons for neurites located away from the center of a chunk to suddenly jink towards the center of the chunk at chunk boundaries.

Related Projects

Several classic algorithms had to be specially tuned to make this module possible.

  1. edt: A single pass, multi-label anisotropy supporting euclidean distance transform implementation.
  2. dijkstra3d: Dijkstra's shortest-path algorithm defined on 26-connected 3D images. This avoids the time cost of edge generation and wasted memory of a graph representation.
  3. connected-components-3d: A connected components implementation defined on 26-connected 3D images with multiple labels.
  4. fastremap: Allows high speed renumbering of labels from 1 in a 3D array in order to reduce memory consumption caused by unnecessarily large 32 and 64-bit labels.
  5. fill_voids: High speed binary_fill_holes.
  6. xs3d: Cross section analysis of 3D images.

This module was originally designed to be used with CloudVolume and Igneous.

  1. CloudVolume: Serverless client for reading and writing petascale chunked images of neural tissue, meshes, and skeletons.
  2. Igneous: Distributed computation for visualizing connectomics datasets.

Some of the TEASAR modifications used in this package were first demonstrated by Alex Bae.

  1. skeletonization: Python implementation of modified TEASAR for sparse labels.

Credits

Alex Bae developed the precursor skeletonization package and several modifications to TEASAR that we use in this package. Alex also developed the postprocessing approach used for stitching skeletons using 50% overlap. Will Silversmith adapted these techniques for mass production, refined several basic algorithms for handling thousands of labels at once, and rewrote them into the Kimimaro package. Will added trickle DAF, zero weighted previously explored paths, and fixing borders to the algorithm. A.M. Wilson and Will designed the nucleus/soma "avocado" fuser. Forrest Collman added parameter flexibility and helped tune DAF computation performance. Sven Dorkenwald and Forrest both provided helpful discussions and feedback. Peter Li redesigned the target selection algorithm to avoid bilinear performance on complex cells.

Acknowledgments

We are grateful to our partners in the Seung Lab, the Allen Institute for Brain Science, and the Baylor College of Medicine for providing the data and problems necessitating this library.

This research was supported by the Intelligence Advanced Research Projects Activity (IARPA) via Department of Interior/ Interior Business Center (DoI/IBC) contract number D16PC0005, NIH/NIMH (U01MH114824, U01MH117072, RF1MH117815), NIH/NINDS (U19NS104648, R01NS104926), NIH/NEI (R01EY027036), and ARO (W911NF-12-1-0594). The U.S. Government is authorized to reproduce and distribute reprints for Governmental purposes notwithstanding any copyright annotation thereon. Disclaimer: The views and conclusions contained herein are those of the authors and should not be interpreted as necessarily representing the official policies or endorsements, either expressed or implied, of IARPA, DoI/IBC, or the U.S. Government. We are grateful for assistance from Google, Amazon, and Intel.

Papers Using Kimimaro

Please cite Kimimaro using the CITATION.cff file located in this repository.

The below list is not comprehensive and is sourced from collaborators or found using internet searches and does not constitute an endorsement except to the extent that they used it for their work.

  1. A.M. Wilson, R. Schalek, A. Suissa-Peleg, T.R. Jones, S. Knowles-Barley, H. Pfister, J.M. Lichtman. "Developmental Rewiring between Cerebellar Climbing Fibers and Purkinje Cells Begins with Positive Feedback Synapse Addition". Cell Reports. Vol. 29, Iss. 9, November 2019. Pgs. 2849-2861.e6 doi: 10.1016/j.celrep.2019.10.081 (link)
  2. S. Dorkenwald, N.L. Turner, T. Macrina, K. Lee, R. Lu, J. Wu, A.L. Bodor, A.A. Bleckert, D. Brittain, N. Kemnitz, W.M. Silversmith, D. Ih, J. Zung, A. Zlateski, I. Tartavull, S. Yu, S. Popovych, W. Wong, M. Castro, C. S. Jordan, A.M. Wilson, E. Froudarakis, J. Buchanan, M. Takeno, R. Torres, G. Mahalingam, F. Collman, C. Schneider-Mizell, D.J. Bumbarger, Y. Li, L. Becker, S. Suckow, J. Reimer, A.S. Tolias, N. Maçarico da Costa, R. C. Reid, H.S. Seung. "Binary and analog variation of synapses between cortical pyramidal neurons". bioRXiv. December 2019. doi: 10.1101/2019.12.29.890319 (link)
  3. N.L. Turner, T. Macrina, J.A. Bae, R. Yang, A.M. Wilson, C. Schneider-Mizell, K. Lee, R. Lu, J. Wu, A.L. Bodor, A.A. Bleckert, D. Brittain, E. Froudarakis, S. Dorkenwald, F. Collman, N. Kemnitz, D. Ih, W.M. Silversmith, J. Zung, A. Zlateski, I. Tartavull, S. Yu, S. Popovych, S. Mu, W. Wong, C.S. Jordan, M. Castro, J. Buchanan, D.J. Bumbarger, M. Takeno, R. Torres, G. Mahalingam, L. Elabbady, Y. Li, E. Cobos, P. Zhou, S. Suckow, L. Becker, L. Paninski, F. Polleux, J. Reimer, A.S. Tolias, R.C. Reid, N. Maçarico da Costa, H.S. Seung. "Multiscale and multimodal reconstruction of cortical structure and function". bioRxiv. October 2020; doi: 10.1101/2020.10.14.338681 (link)
  4. P.H. Li, L.F. Lindsey, M. Januszewski, Z. Zheng, A.S. Bates, I. Taisz, M. Tyka, M. Nichols, F. Li, E. Perlman, J. Maitin-Shepard, T. Blakely, L. Leavitt, G. S.X.E. Jefferis, D. Bock, V. Jain. "Automated Reconstruction of a Serial-Section EM Drosophila Brain with Flood-Filling Networks and Local Realignment". bioRxiv. October 2020. doi: 10.1101/605634 (link)

References

  1. M. Sato, I. Bitter, M.A. Bender, A.E. Kaufman, and M. Nakajima. "TEASAR: Tree-structure Extraction Algorithm for Accurate and Robust Skeletons". Proc. 8th Pacific Conf. on Computer Graphics and Applications. Oct. 2000. doi: 10.1109/PCCGA.2000.883951 (link)
  2. I. Bitter, A.E. Kaufman, and M. Sato. "Penalized-distance volumetric skeleton algorithm". IEEE Transactions on Visualization and Computer Graphics Vol. 7, Iss. 3, Jul-Sep 2001. doi: 10.1109/2945.942688 (link)
  3. T. Zhao, S. Plaza. "Automatic Neuron Type Identification by Neurite Localization in the Drosophila Medulla". Sept. 2014. arXiv:1409.1892 [q-bio.NC] (link)
  4. A. Tagliasacchi, T. Delame, M. Spagnuolo, N. Amenta, A. Telea. "3D Skeletons: A State-of-the-Art Report". May 2016. Computer Graphics Forum. Vol. 35, Iss. 2. doi: 10.1111/cgf.12865 (link)
  5. P. Li, L. Lindsey, M. Januszewski, Z. Zheng, A. Bates, I. Taisz, M. Tyka, M. Nichols, F. Li, E. Perlman, J. Maitin-Shepard, T. Blakely, L. Leavitt, G. Jefferis, D. Bock, V. Jain. "Automated Reconstruction of a Serial-Section EM Drosophila Brain with Flood-Filling Networks and Local Realignment". April 2019. bioRXiv. doi: 10.1101/605634 (link)
  6. M.M. McKerns, L. Strand, T. Sullivan, A. Fang, M.A.G. Aivazis, "Building a framework for predictive science", Proceedings of the 10th Python in Science Conference, 2011; http://arxiv.org/pdf/1202.1056
  7. Michael McKerns and Michael Aivazis, "pathos: a framework for heterogeneous computing", 2010- ; http://trac.mystic.cacr.caltech.edu/project/pathos

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kimimaro-5.8.4.tar.gz (528.2 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

kimimaro-5.8.4-cp314-cp314t-win_amd64.whl (327.5 kB view details)

Uploaded CPython 3.14tWindows x86-64

kimimaro-5.8.4-cp314-cp314t-win32.whl (284.8 kB view details)

Uploaded CPython 3.14tWindows x86

kimimaro-5.8.4-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

kimimaro-5.8.4-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

kimimaro-5.8.4-cp314-cp314t-macosx_11_0_arm64.whl (340.8 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

kimimaro-5.8.4-cp314-cp314t-macosx_10_13_x86_64.whl (363.3 kB view details)

Uploaded CPython 3.14tmacOS 10.13+ x86-64

kimimaro-5.8.4-cp314-cp314-win_amd64.whl (310.0 kB view details)

Uploaded CPython 3.14Windows x86-64

kimimaro-5.8.4-cp314-cp314-win32.whl (261.7 kB view details)

Uploaded CPython 3.14Windows x86

kimimaro-5.8.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

kimimaro-5.8.4-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

kimimaro-5.8.4-cp314-cp314-macosx_11_0_arm64.whl (320.1 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

kimimaro-5.8.4-cp314-cp314-macosx_10_13_x86_64.whl (350.3 kB view details)

Uploaded CPython 3.14macOS 10.13+ x86-64

kimimaro-5.8.4-cp313-cp313-win_amd64.whl (301.8 kB view details)

Uploaded CPython 3.13Windows x86-64

kimimaro-5.8.4-cp313-cp313-win32.whl (259.4 kB view details)

Uploaded CPython 3.13Windows x86

kimimaro-5.8.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

kimimaro-5.8.4-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (2.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

kimimaro-5.8.4-cp313-cp313-macosx_11_0_arm64.whl (319.2 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

kimimaro-5.8.4-cp313-cp313-macosx_10_13_x86_64.whl (347.9 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

kimimaro-5.8.4-cp312-cp312-win_amd64.whl (302.1 kB view details)

Uploaded CPython 3.12Windows x86-64

kimimaro-5.8.4-cp312-cp312-win32.whl (257.9 kB view details)

Uploaded CPython 3.12Windows x86

kimimaro-5.8.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

kimimaro-5.8.4-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

kimimaro-5.8.4-cp312-cp312-macosx_11_0_arm64.whl (320.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

kimimaro-5.8.4-cp312-cp312-macosx_10_13_x86_64.whl (348.7 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

kimimaro-5.8.4-cp311-cp311-win_amd64.whl (304.0 kB view details)

Uploaded CPython 3.11Windows x86-64

kimimaro-5.8.4-cp311-cp311-win32.whl (259.9 kB view details)

Uploaded CPython 3.11Windows x86

kimimaro-5.8.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

kimimaro-5.8.4-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (2.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

kimimaro-5.8.4-cp311-cp311-macosx_11_0_arm64.whl (317.0 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

kimimaro-5.8.4-cp311-cp311-macosx_10_9_x86_64.whl (351.8 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

kimimaro-5.8.4-cp310-cp310-win_amd64.whl (302.3 kB view details)

Uploaded CPython 3.10Windows x86-64

kimimaro-5.8.4-cp310-cp310-win32.whl (260.8 kB view details)

Uploaded CPython 3.10Windows x86

kimimaro-5.8.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

kimimaro-5.8.4-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

kimimaro-5.8.4-cp310-cp310-macosx_11_0_arm64.whl (318.9 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

kimimaro-5.8.4-cp310-cp310-macosx_10_9_x86_64.whl (353.9 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

kimimaro-5.8.4-cp39-cp39-win_amd64.whl (302.6 kB view details)

Uploaded CPython 3.9Windows x86-64

kimimaro-5.8.4-cp39-cp39-win32.whl (261.2 kB view details)

Uploaded CPython 3.9Windows x86

kimimaro-5.8.4-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

kimimaro-5.8.4-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

kimimaro-5.8.4-cp39-cp39-macosx_11_0_arm64.whl (319.7 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

kimimaro-5.8.4-cp39-cp39-macosx_10_9_x86_64.whl (354.3 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

Details for the file kimimaro-5.8.4.tar.gz.

File metadata

  • Download URL: kimimaro-5.8.4.tar.gz
  • Upload date:
  • Size: 528.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4.tar.gz
Algorithm Hash digest
SHA256 decf5613e65f65fcefa1371c2524956cd4f3a2ef56c2732a0156afa92e8375fc
MD5 619c0330ef1bcb6e79a69f0668fcffd1
BLAKE2b-256 b8ee4a914e0d6ce86aa21bf0403498a51d251ea720d778c7b2eea55f01efb81e

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314t-win_amd64.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp314-cp314t-win_amd64.whl
  • Upload date:
  • Size: 327.5 kB
  • Tags: CPython 3.14t, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 afd0fff808f9806c1ca03ce8e186798abc6667656a7e372c9f28bf35a9526043
MD5 79d702822c97a87031ce44816dd15357
BLAKE2b-256 c654dcd4199af8cd4cd68032bf01f1fb66be6d9bee5506042e9b1b9453bd4509

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314t-win32.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp314-cp314t-win32.whl
  • Upload date:
  • Size: 284.8 kB
  • Tags: CPython 3.14t, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314t-win32.whl
Algorithm Hash digest
SHA256 df5b0563eb1877c59ba9bafbd1a63be43c9c392e66ee76da561c09fd08f76cd3
MD5 2226e883e29de6b810c54d9f3b9c7660
BLAKE2b-256 7f293b6b12930f839d335be2e29f7f7860bd86b28d2224ea68dbd5a57d05d356

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 024f4e67a72508c057275a1a6a6bb45a3e70287f36ea0e0920834791f2398238
MD5 97843c76a2889d6af2164fafad5cc283
BLAKE2b-256 a4c5555253c8d923649dc88cb91d654401c10ec5a1041316717c3514f4782461

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 20ec710d494f8284fe14a654f8368c3b62c7815cc1dada0871d79e327be9e3d6
MD5 6b05073e6d18b9e0e8be7552e33370c1
BLAKE2b-256 a968c2bc9753570dc53e058dd893e648ce32f4e19fc8f81167f69edfa6fdf295

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ac0f4dfe7e693febf17b8d3891e5b1781ed878145ddeec8ae6f948cb112a53c3
MD5 4c0e43704aaefd45a3bb367b398af1ef
BLAKE2b-256 719fef0dd51e92ef2dcec5a9f347a91554c1e8ac93ea6663038163bb83facb80

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314t-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314t-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 85acde94a406ca02d9d48bd1270e0d344a5277a022998f959b1e04eff05c27cb
MD5 0fc3916b68c6ed9eff03ccb27e31c134
BLAKE2b-256 a1d32052dc517a32ebb8d0d138f8a4b744b69dca42bc730fd1222f33d3790157

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 310.0 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 195c76dc10e33b80fb9e3f590ffe7e7e1b2d2b5d75dc8d089bbdb84efbbc7bde
MD5 38ec72abb183207071f231391ab9d5d4
BLAKE2b-256 803dc64ce26df3b162bd1bcc40314c5b2419a2f9bb96a8c76a1f6af4f2e9b4a7

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314-win32.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp314-cp314-win32.whl
  • Upload date:
  • Size: 261.7 kB
  • Tags: CPython 3.14, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314-win32.whl
Algorithm Hash digest
SHA256 14607bc6edf526a685d61a7c873e619c5f5fb3d751fbddb96e5db2e537716013
MD5 7567b510e8eb3c3a4a7666bc47c6b4b0
BLAKE2b-256 516525132eff6a9027c6f2d387dd0453a0615880e0472adb75f0b2fb78d0b0d5

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5a8448088958aa63a82caf2c0e304ad2a0c861375e6ba2c85f2d7885c09c7259
MD5 79f1bd3faa41a5bde5696b4702c54625
BLAKE2b-256 8a4060421500b2e0e87cca3485baa512b131bfd8559b86c9cd80d868d5d3b55f

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b459a347a57f801738b06b91e4efa16ef401c1d398d30e3813efec9a07f76735
MD5 29c88f2be0d5ac863caf80a925f6c307
BLAKE2b-256 5017070cfe743727096316b81fa7561477d0220e99d483a6a1cac61927b10121

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 096fbdb175a72602d3195851a503b57dc2d9599fdfcf0f2f5a1d713791873030
MD5 99def3d23ee23ff26e4325bbdc1b7796
BLAKE2b-256 3da50b796e9ab39ec8329ea00afd0b6d7805ed6797d3264eeedcccc4808397a7

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp314-cp314-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp314-cp314-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 0c4e9af7dae62ec79b05730905c8bef9215e5f3cfc9b0541d010c3c5ff82b408
MD5 c1d2a9dc19be9047ba6c83b4de327858
BLAKE2b-256 39900d459968a91b6e006369bed9548af04560d9e0f22732715ec771ec455b7d

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 301.8 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 01d6b64bc98081b0bcb513726f2a15dda9296b8a8495a1660d55f5a526301627
MD5 cb4c7e0ccecece4dc22290284d92394f
BLAKE2b-256 3ef31d623d106cb73b0ded5b423a5fc5e79e13bb7a6769b49e4438483511b4be

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp313-cp313-win32.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp313-cp313-win32.whl
  • Upload date:
  • Size: 259.4 kB
  • Tags: CPython 3.13, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp313-cp313-win32.whl
Algorithm Hash digest
SHA256 cb72044d9cf8af08af924780991ac181914cfcd33581300010beee4bb2cd874f
MD5 190eab7f559be9b5ed9c3ad97a45b352
BLAKE2b-256 593ce8d8f5db8159109e4088d98f64a991630a53abcb102197ee33c53b09ad7f

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 516ed91761275bfbec6383776d4727752666883d7844cb10e34d1432e5b7a93e
MD5 62fad2b59b766f73b14020687eb5212a
BLAKE2b-256 b6c6ab8becee980ba87e728eb1824b5142c97139199b4198612a71f9377bac0d

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6e751fb19a11bbfade5d1d91e4f0dedb27813e49200a7bc0c55cd30913295b4a
MD5 1274a6d81391017d956efc154527d21c
BLAKE2b-256 081bd245f7147d2da47c7179aa8ac8010d8fd96a31ec99779647e88bfe4649b9

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9045c4a76244f326463afced587b01c1d7655c7e636395681b31c741ef424f5e
MD5 d43e023807df0f05228f8a404e6ff3e3
BLAKE2b-256 285b415ed1203a3c3ba898a70771c3522218857a666f2d9136a5fd9d62bf72ea

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 60f863f12900bf624a24de7512a71feadb8c599ab76e41e461ebcd1ad9f19df9
MD5 26ed09051702d0419b0500441b7dec25
BLAKE2b-256 50492d6d8b4490a460534f9b04d7c6b34e6e39a87c016ec97efa37f3d43b24e9

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 302.1 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 4d9a861fc03ac451d5a097d02475d0047afa0f7e7030e7ca83c7417569f36ffc
MD5 6b11760630f85d6d7f32f8051caac8f4
BLAKE2b-256 1eb175965cf45d9cdd05a6aab5849a63aa3a1797273131eba74970e4cb023691

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp312-cp312-win32.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp312-cp312-win32.whl
  • Upload date:
  • Size: 257.9 kB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 23e0c4870eba8d1ef40659740393b3fe43fc7ad6d3996ea443e161874ac280ed
MD5 258b7c35bc5a69021e78166844361741
BLAKE2b-256 2701bd799147098de723ec6180ca4bcae50c6b0a9ebd67647923a2a86e32c112

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 565e1802ead6dd42cebc8fa86ba129241b589dc71a820a8baa8ca1ecc1175570
MD5 22e84974e4b544a7f6498958ff82b5d7
BLAKE2b-256 acb2f6c5b027aa436efda2c2a7976a7d669becb58d628fe1764d5c17657c88c0

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 55f8981e9aa9505cecfcddc2da810679180e241796e20c481ab3d5ac7c4cc1ff
MD5 ddc6c580e0b8f33119bf0351b697b817
BLAKE2b-256 dcdabbf414e509dc0d00337f8184aed2711a10ef9e5df76886b80a6156c39317

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f78bb5e4e19cb9422af198a0c7ddd08a5c32371df448b7f8ecd4a7abcc68db3e
MD5 5fb330626f8ebc64b81a883815c40e0c
BLAKE2b-256 649dc86a5e0221d4227b10d60300fd6acb799b90ff230a979c2d27d6e655753f

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 e349c92109ceab940393473e9e156675db5cc26704b759574122ef01c7061ae2
MD5 dcfe05139aa5b0dcf439747a8221e990
BLAKE2b-256 c41cc2c07352bf155c5eff10890ce6fb2140b3e0475c88c7115a8f692ca69e0d

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 304.0 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 14fa846f06ea6d75e692e48995c8a3d03076142fa2ce6046468c00a48526790b
MD5 22affa1a7441750496d06b1d741edab1
BLAKE2b-256 80bb52a2063a71a4b2b6ed1e2a6c1d796451ad9f69ee22195ca7c28b62e7b707

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp311-cp311-win32.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp311-cp311-win32.whl
  • Upload date:
  • Size: 259.9 kB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 d560d501a597223bfb06a8eb01725d816795e22d5d3de0f5c206997a6933f262
MD5 449dcefed309e04cdfc494f89e852d41
BLAKE2b-256 27c9aba25ddf6d93a8e03c1ed37085c260450ccae3225de3927526ecb811c48c

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 109e4b27e2796a8a827304472290a1c7e439d4e7d0c146c58b542556e7fac3bf
MD5 c54ee34ed86ad4f890cc5e98b1dcfd1f
BLAKE2b-256 19b42d6111a8d42e4c395d1688489564866287bb0d59fe2a2717b8bbd38c02ee

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 5df4911cc015fd9c114f9d5e25f71bebd592c5b0225e906948fbe462f9cd117d
MD5 1fbec833763dee972cd7176eb6f65bf4
BLAKE2b-256 13a4ebe9237263c963841283fbd35761a70f15d755c01e3d9b2f08ac8454c2a7

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bd8c255749929270d120438c98c9e69a317829735e40ffdb14648b4b3e0c23c0
MD5 896ae70e68aa6472a7cac7cea66ee7f4
BLAKE2b-256 ae0f667bbcd676337c8e95ff45210bcf9f5499a76b0dcbd5d89ac73c346cb0f4

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 cfc6196851ecbccef8ffdd68768161a7c479a969c162b3af73be4270126bfb26
MD5 f9b9d4b09a51c5e3f110be781e35be12
BLAKE2b-256 ed56f779c50d1575708bb0aac2226cef86d61a5d362a5c6e58867ccc017ebe29

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 302.3 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 35b82db324b4c4cd0e255a396e997d3c327d2804aba23a473aafd12eecca2a12
MD5 a8ac9eede51397afffd69e97acac534e
BLAKE2b-256 2d848ef8b01ddfa528c2bfbc33362cf940091e0f22e08e997cefa59dc153f913

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp310-cp310-win32.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp310-cp310-win32.whl
  • Upload date:
  • Size: 260.8 kB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 7c0a4ca35a96404b097bb17162447ca75217c1fd1e057a26d4f95a0f8fcaf45b
MD5 5180158afaf016f46a48e8e41073e142
BLAKE2b-256 0e072bf8bf98953c976384a045d8843177481e4e79f3fe0fd8c030c9f66e707a

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1d2f836dc5f199354cece11272751793d1568e4a21cfe1fd2f57da4513244bba
MD5 4df86a5e2179a5f38791fa48dd63f6d6
BLAKE2b-256 7fbaeb4e6808b3592216747a5745b6c05749324deafe23a899fdf68eaff5a515

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d135c71534ed35a87c54c49fca3d17f29ca4a531ac61e7e75e30879da0976e91
MD5 be9b13501a7d2be7fe3b68f20e01c1e6
BLAKE2b-256 3c34318266cfbcf03599b2424bdf2bece74d05e3edde8fc7474281553baff5ab

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6a6a7a1f2958c82bce5d7ab72fdcf9fdb48097d5bdafc11634c10d85851403dd
MD5 1750ae3d564e82c606a7397fbd8c32b0
BLAKE2b-256 535987d22adfa26f349617a674105b689de50110e121d2264381d3496fd82795

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4e06ffcf7c84b1257b45277a36d4af8f59ae52dbf03d7283fbdcf7196de60590
MD5 de5da91366054d260a68f15fcb914c2d
BLAKE2b-256 846cb0b4dd2a746c1e7ec583d2ca3d82fa1826bcb1b26b5bf34a7435385b4b9d

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 302.6 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 9bf8df597553ba8ab9da114d0caf434d7dcbbf73aa01c99dc0d341c3fd6b3568
MD5 499634163ecc483ea63fb6d58fb64316
BLAKE2b-256 19469cf6149595e17bb37cb35838843ebd33ff31ab8076bb75c4a307e557b17a

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp39-cp39-win32.whl.

File metadata

  • Download URL: kimimaro-5.8.4-cp39-cp39-win32.whl
  • Upload date:
  • Size: 261.2 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.3

File hashes

Hashes for kimimaro-5.8.4-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 6a44717ef243f78b761d52af89effd62adb809815b154f30c28bfe8bce595de4
MD5 da8e1aa5d3e36f19a71a87b182cde640
BLAKE2b-256 9f24431ec98accb02e614cab4cf650e4b443722fd23f565c5c859bd12a81c936

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 93a52bb71289eb7d7d5f79083ed8f159c88b7e8b5158015b38901c35a96fde54
MD5 c3b70e12eac7b79c1b4e52ed75d2147c
BLAKE2b-256 4ce97ed437a7912c7b4764aa79da430036c1dee2b2a37dab908547b2d983bd31

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a7872c90b3e182dd9aeff0a63e6ed7459a9fe62feb62b6aa8226bd480dcf3d50
MD5 a28b782d2ece9d78cd5e0f730de67a94
BLAKE2b-256 03c83c646cba44c63dfc18d17f335f4acd657cbcc0332aef8fe85a0ef6513623

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 95e0530cc3109a1d892a06f4b0e7c58e2a3c048f97ee9260333aebff60d661e9
MD5 b7e21d2404dbec8a4486cdf5aba6165f
BLAKE2b-256 4d55194e859d7d82e6ec75327022a5e9249879283d8bca4b48f544875451b19e

See more details on using hashes here.

File details

Details for the file kimimaro-5.8.4-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for kimimaro-5.8.4-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 9acca3f7c9a0839a65b9d05fe2ab8599079fe8024abd51af76989186eb5986fe
MD5 94dd12492b1d5135b984dfa3deb295d9
BLAKE2b-256 c64eff84ab128438692f12e9ff1a0efc8cfc9095f6da546e015a7dd4ff6721ae

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page