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.3.tar.gz (527.8 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.3-cp314-cp314t-win_amd64.whl (326.2 kB view details)

Uploaded CPython 3.14tWindows x86-64

kimimaro-5.8.3-cp314-cp314t-win32.whl (281.2 kB view details)

Uploaded CPython 3.14tWindows x86

kimimaro-5.8.3-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.3-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.3-cp314-cp314t-macosx_11_0_arm64.whl (340.6 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

kimimaro-5.8.3-cp314-cp314t-macosx_10_13_x86_64.whl (363.2 kB view details)

Uploaded CPython 3.14tmacOS 10.13+ x86-64

kimimaro-5.8.3-cp314-cp314-win_amd64.whl (310.5 kB view details)

Uploaded CPython 3.14Windows x86-64

kimimaro-5.8.3-cp314-cp314-win32.whl (261.5 kB view details)

Uploaded CPython 3.14Windows x86

kimimaro-5.8.3-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.3-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.3-cp314-cp314-macosx_11_0_arm64.whl (319.9 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

kimimaro-5.8.3-cp314-cp314-macosx_10_13_x86_64.whl (350.1 kB view details)

Uploaded CPython 3.14macOS 10.13+ x86-64

kimimaro-5.8.3-cp313-cp313-win_amd64.whl (301.7 kB view details)

Uploaded CPython 3.13Windows x86-64

kimimaro-5.8.3-cp313-cp313-win32.whl (259.2 kB view details)

Uploaded CPython 3.13Windows x86

kimimaro-5.8.3-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.3-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.3-cp313-cp313-macosx_11_0_arm64.whl (318.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

kimimaro-5.8.3-cp313-cp313-macosx_10_13_x86_64.whl (347.7 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

kimimaro-5.8.3-cp312-cp312-win_amd64.whl (301.5 kB view details)

Uploaded CPython 3.12Windows x86-64

kimimaro-5.8.3-cp312-cp312-win32.whl (257.7 kB view details)

Uploaded CPython 3.12Windows x86

kimimaro-5.8.3-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.3-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.3-cp312-cp312-macosx_11_0_arm64.whl (319.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

kimimaro-5.8.3-cp312-cp312-macosx_10_13_x86_64.whl (348.4 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

kimimaro-5.8.3-cp311-cp311-win_amd64.whl (304.2 kB view details)

Uploaded CPython 3.11Windows x86-64

kimimaro-5.8.3-cp311-cp311-win32.whl (259.5 kB view details)

Uploaded CPython 3.11Windows x86

kimimaro-5.8.3-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.3-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.3-cp311-cp311-macosx_11_0_arm64.whl (316.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

kimimaro-5.8.3-cp311-cp311-macosx_10_9_x86_64.whl (351.7 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

kimimaro-5.8.3-cp310-cp310-win_amd64.whl (303.4 kB view details)

Uploaded CPython 3.10Windows x86-64

kimimaro-5.8.3-cp310-cp310-win32.whl (260.1 kB view details)

Uploaded CPython 3.10Windows x86

kimimaro-5.8.3-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.3-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.3-cp310-cp310-macosx_11_0_arm64.whl (318.8 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

kimimaro-5.8.3-cp310-cp310-macosx_10_9_x86_64.whl (353.8 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

kimimaro-5.8.3-cp39-cp39-win_amd64.whl (303.6 kB view details)

Uploaded CPython 3.9Windows x86-64

kimimaro-5.8.3-cp39-cp39-win32.whl (260.5 kB view details)

Uploaded CPython 3.9Windows x86

kimimaro-5.8.3-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.3-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.3-cp39-cp39-macosx_11_0_arm64.whl (319.4 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

kimimaro-5.8.3-cp39-cp39-macosx_10_9_x86_64.whl (354.0 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: kimimaro-5.8.3.tar.gz
  • Upload date:
  • Size: 527.8 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.3.tar.gz
Algorithm Hash digest
SHA256 c3aefc59fe65940ca3022f15918e0b8e6def499b4fff1fb8ff9bd5feaedb1c39
MD5 f56e3ff55758dfc11ea378bbeaebf527
BLAKE2b-256 5bf3662c1c4a6b3bf63d176623e019bfa3f47b8c616214496451ef36eba680a0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp314-cp314t-win_amd64.whl
  • Upload date:
  • Size: 326.2 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.3-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 d081696a99c98f55fb0595b08f5aaf2a120f429c6d85c7cf9e6f93e1be622aa3
MD5 0a685099d2d7a01ee9a13aeed31499dd
BLAKE2b-256 8262bffa62848040b9ce208aa5650b8d466229c142b2ef4e5f3d2cc82e178ba8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp314-cp314t-win32.whl
  • Upload date:
  • Size: 281.2 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.3-cp314-cp314t-win32.whl
Algorithm Hash digest
SHA256 ae44e52c4360b9afd4e1e9992d0c6ed2276d77e9a8451559191bb1d4a4411f82
MD5 6b61f7c30c86d1f8ec67971fd11584ba
BLAKE2b-256 13def4f163333e153c2daa2f2779c2f9d2914e7b8711c1a0183f15ca725f5254

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d9b857a752833b77d45f8e3f8865e4f04be80345d2aaba308c468bc72f5fd3e7
MD5 ca554e5b37499e3a0e6247f20c3fff82
BLAKE2b-256 0c642c3257d88235e259868224138fea7282d48a8033696a9d5475b4d88abcf1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 67087b75fbc04b0c3062468deb4d5a41b830d87b57f96c4bc47e8a7d5eade620
MD5 70990c92b89354f482a1026af51b8d8d
BLAKE2b-256 e6f30edc0c7dccb749e01544c513357dc3c4fc8a93654902e01ca84327e3828c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 57f41ff35a905de64654664849e677c8865d3b775d667aa34e689bedf5b8740b
MD5 5a76cd279a92e13fa7a974ea9f6254bf
BLAKE2b-256 6cbbcb8a52a9ea00e160fa51a2e35fecb541fb2306eb49c2b680cf3a3e91d3e7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp314-cp314t-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 c44bc2500100080c013d24424fbd249602681e8a988c2c1232282a95c1575a9e
MD5 0064ce8b10dd8d53fbda2665c164303e
BLAKE2b-256 d7b2cd6858dab217aec1283a939480ef5ade800349801473c855ce48ec29dd16

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 310.5 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.3-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 fbe7c0cc0a96c7ca5893dbcc2a4d03e12060dd2cd009d9cd7460c20ba8c40d91
MD5 e4f80eb0acb1824e21c135c216e2d827
BLAKE2b-256 bedd8d1efdb3e725f01171642de5a26fb97af6dc253665bd3fd1507f3aa982f2

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp314-cp314-win32.whl
  • Upload date:
  • Size: 261.5 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.3-cp314-cp314-win32.whl
Algorithm Hash digest
SHA256 26d5af8d4ad5d29f8164880d31186405c94e4a321f9dae21c2ae08021e03d973
MD5 69c3dddd866691ddedcb59f766f77ea4
BLAKE2b-256 52d4361223eac98cb6c946bc235151c0871e21e0a3236574cc603980e842df3b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 611e178c4bdb38bc6a85533b02c8a2ec497c0e8bd7ae10e801e12cb4d740cc58
MD5 25eeaa8d74e7d85795203224095db855
BLAKE2b-256 7fec5c60fb43cd2d1e4641c7ba01a751448c4c9e467c7197eb4f34c9f0723d84

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 1f2de653db832af952ae8b79fa10c1179f9779ba7045f907dcdd337a4cdd86ab
MD5 14b41dfe7b1f346baa2c11e43c0e9f28
BLAKE2b-256 f7306a09938405c7341bc46fd5d4a2112bf02ffff863de0924d1196cb1c9f310

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 557de463bddbaf4d3d688850aaeb995d1217e5f686e7d2da1a4308b46af94fdc
MD5 bd8f3f316a9e730be6145108d244cf88
BLAKE2b-256 ac13331f8a1254d8703851712fb9466c11496b23773c2168beb0fad28d82330b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp314-cp314-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 3b2f1726789b0e5a0d966b8e518e2d41f956026e60c4be0e4a688204c759840e
MD5 281feff47616938ad30fb672e970668e
BLAKE2b-256 36cf149c55d2a52b572f03411604b53699ec01e291bed7495f97be994c7f5364

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 301.7 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.3-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 4c9506cf3b55e72b9311fd0f5ae16b651ee1b5a598776a836765f63887be293e
MD5 5685608ae113fd75cfead9bbc7c7e462
BLAKE2b-256 15dd8a34553bc45100ca989648ba0bd4dacf048a3ff132368e6592db77c45e25

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp313-cp313-win32.whl
  • Upload date:
  • Size: 259.2 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.3-cp313-cp313-win32.whl
Algorithm Hash digest
SHA256 f71cf207d6c8119e90e41b34304fb74f1215ea2752dc14dfe0b0c3af4f47b82b
MD5 670806bfa59d2607608c4f89525140a7
BLAKE2b-256 7834d0451ac2ca6818d2474894fa1b74d0a45ee295207a3061b97b1131af0bf9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 591bdcb45941e6ae7648343fad3f429aea84cdf8a49344a53240bd838070cf78
MD5 07ee9ff1ab9f3956fdfc51fc1d810ae3
BLAKE2b-256 0fef9f6ac97443fdddc184952dba1d42437b11689c7cef99cc51d7faafd2b543

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 71fb7551994b81f94e9fe5d7267b56ad91d8808e9515d7f49671097fdd951e50
MD5 8679043d07be0bd47f08c0edc93005ca
BLAKE2b-256 9d06c4ebcead4b4a17f9b1649ad82b45b1640b5f0a4fab3ca3c99f55714e4426

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b9920fe1d6b7c707b8ebe270e1bc1e532a9584fe8bdfdb97e50b2c8b35359978
MD5 94380f83ec64920eff2d68b8fddcb90e
BLAKE2b-256 54211ccc4555edd6eb799f922b945534f88728f9a93545901297518a61e98f8e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 1650df8b706899ec3884778f26bfae982d54f345e8e4442806e4e970af033110
MD5 a6e73815ddebf892ce7554935e3582bc
BLAKE2b-256 b4bbf2213ca5bde4faab7ed5834cbce56b16d37c8ca7b4346ccbdac85258800f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 301.5 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.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 3f1b906cb95d83183ab7a93ef42cca199fb6ac26925cd654866a04e9e367905f
MD5 b4db26ded1c38e4c60e8941fbf8f43ee
BLAKE2b-256 d50d8508baace2e7b3a0112dd731130ae89bc5751aefd28d9e714e0f0a335aeb

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp312-cp312-win32.whl
  • Upload date:
  • Size: 257.7 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.3-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 742b971f80c0d6221f93b9060407d08ec91947028f56ba56c92144d82aed1334
MD5 f789cf74b229a9277f2b220afd373194
BLAKE2b-256 17dc209c93da925ce8fd9d2314461ddcd9b8e9256d798e1f2edac69a13d7b9ba

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0dc4a3c00abe9ca717c36062da488486fc61e19d42f8e586633f50df6edc495b
MD5 1c4df0d7c50567b0ea099f61f92ef85a
BLAKE2b-256 3f4c51d85bb037234ddf96801e066b2ed3b5bc341f637eafcc02d641c76a2a47

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7eb86fdda3e3062afcb901f73531c73a6cdd18bb8bca19d35c60b264b75267a8
MD5 556be85b11967c6ef6b8b8f74c7f215d
BLAKE2b-256 9f93a91cc43f348abe9d36daf83471c4a7bbc01822f10e07ce4dd3df2ba7ab5c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 56bcd03452418a3687e1c5629be00d57cf3591d777d705a03505c13b182be5dc
MD5 c903d2fe61d2bdd73bbe266c9bb8c410
BLAKE2b-256 a9df9dce0f12c2f2d6cf2dfd76857250113e99c46f03f7c1f8d85cc9a8b373ca

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 87ef28b92e20ee43660eef2fe4c5d5802a584e5efbc910902a8ec3d05f124b15
MD5 20f456b011bd54ac088d01945111a6a2
BLAKE2b-256 93dcff85002bb69b54af7a3e51164b35f2db92c228fdbc29dd5827e200ba79b9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 304.2 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.3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 4f34777f98b5d01b4145487bcadd433ce10d1ab1900a06dec292b36fac178b1a
MD5 26844c90a7de92d1af2be7a987bf5736
BLAKE2b-256 a7b8b753c216a668ac3cf3b4c1c8f799aa6d3eb7df8aaff669eb662e5a367a04

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp311-cp311-win32.whl
  • Upload date:
  • Size: 259.5 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.3-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 46ca73767f2c25459add39bc5fe846a9930d8b642ff5ccb997dad575b1aaabab
MD5 43387b80403f73fbde7708932548a7db
BLAKE2b-256 d00218a861e822974061de89607efc1ec296ca94e3b0eb25dc2ee0712cf241bb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 af3db09056ec4bd79936585ee297ac01a928fcae0259e430a4a09f1006d00c0d
MD5 64c363c0614136370478bdb359854dfa
BLAKE2b-256 7cf5a0707b2dc2d1f047232a5efa917e2497d5941c020711d991b2903cd06354

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 65659d9197be0a6bad6b1f66eb159b6b928aedbaf14679cb85f43560628a4621
MD5 ed3eed7ab6f017feef5d6e844c80dff4
BLAKE2b-256 6c464728018db45d527809131caf4ef15611dd31de8553a648ccea65d553e817

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 36d6888103905819e14346b53a22e78c0c1c5d85af0e57696aa52650b1237e7f
MD5 055410cd92b3bf2f3fe59ef860f2a843
BLAKE2b-256 dd9dfef86feff59822faeb0099ffd2f50d57aaa39bcc2b8e6340a72d2040642e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 005553e6348fe5c6a37a6c45e8728c29190f9799988bc3265ce9de01cd83ad26
MD5 420ba476e70fe7d88fcb1ba1f91f10f7
BLAKE2b-256 1c326f9c17defb49d0c40a3d32147a374e42fba6ff3f652e69f96347846eb7cb

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 303.4 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.3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 8a735e11715205f4ed8cf4a64d4a35a8cffcb7acf09e5a8a17a7eac74c575fff
MD5 69f90e527283994e0302914900db416e
BLAKE2b-256 17e9b559abf93882c06d0c1144370ceea7832fc39d24b27bcbee60da1b90fc62

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp310-cp310-win32.whl
  • Upload date:
  • Size: 260.1 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.3-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 ce0710b2a2b4bc4a4afd067a96be548dabb20c2fb382f0a047005f24c42a3fed
MD5 1b98fe12c09882cafbb36b7480b24d15
BLAKE2b-256 55f1ffe64b3f22e1a3e21eb787601155b7df12c290ea5f268d7fc6e7d118714c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9dc5efc801557ba7f660b06879e13c96b19c849ec21b38468e7a8af77548af60
MD5 e0508aaf7b7a26a7d246fa0ce777d5f7
BLAKE2b-256 a85d2b1ea97659fedd5ede6f0883fb1dfb7801dcf066127141be0abc3fed16f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 2b24f1ae2ba186623a0271fcd7f5d7085f393812097ceb50c36a78a54e7133f4
MD5 82ac5818fee2924ce9065d584d9d06e7
BLAKE2b-256 b7972d5d7289c86ca7312982b297f6df0c02608e8154902fda202862dc94924a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 49c061773e45e72eb921b5201801170563454d11bb10f352b73fbcc1b0866a8e
MD5 07816e845e8c92deb0cb7a3065098145
BLAKE2b-256 189e109babe8b0a2b20e1954628ba4ed2af0a5d7e0914d6bd31cda633b13ffe5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 6b8090eaddf224786c784642e3fb7d0272d32bbdc068c436799d72050f3c9047
MD5 6ef525b64c389b5483107bf2cca39aa5
BLAKE2b-256 5d130fa475428cf75b519101386f411c45b7cf97f444d82708f227dee564ed19

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 303.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.3-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 7f166a894fffebf2f9badc60dbd24f0e5ca793955a6aa31b1a53cc1c1d100812
MD5 adf8d91c8030da0c989229dab66e40f3
BLAKE2b-256 5751631871ca5958fdc6e9442abdba8d76a1de14a7be40529b6367b38ed29c65

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kimimaro-5.8.3-cp39-cp39-win32.whl
  • Upload date:
  • Size: 260.5 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.3-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 6959ddd9f45c99eb9c974fa9d13c509e87baed5b3bfaffa499ed28778f26ef47
MD5 4317a7413718cba15238f61b9ccbd050
BLAKE2b-256 85adcca54fcda4a06e07c9a78501d5244f505b054f71ccb8692049a27994a7cb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3394ed27deb90bba739f6b3eeb5604711b6e41644694da5d79a8b5f47d01787a
MD5 d53228be9b77d3646c52f68d383df989
BLAKE2b-256 72f58a07a3594376149efd402ebaf0e1638a30bf39d4fe7287208c4982089519

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d65f5618b5338f12c07d79650892a4ddd9db5c3e07b47db4cb086a440228bdcc
MD5 7cc91f0e042d5970f56520a959637863
BLAKE2b-256 9e8f774c5a89f79e1497755587eb4acaab6b34c3a47389de2a16a14c9e2922e6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0ea4b169ab718807c66238a3a4246307486ac1a03a945f0d5695c34a8ac7ddfd
MD5 5a141a108eaa9d3c22b1ab822dff43c1
BLAKE2b-256 27298767c322fccb2af8cd3bac799c932e65d301d26341be13dc324325c83eab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for kimimaro-5.8.3-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 21391ca17964e0986d36ce419fe77ca5445d46583d4f6f0f1270e2d59d62fab9
MD5 fb93d835209ad2a26c09e4311e18ad5b
BLAKE2b-256 b59eb466cedec0f298111b031232f7466a28b0d96fce73ce4c2d2cd5c43b16b4

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