Skip to main content

Connected components on 3D images, supports multiple labels.

Project description

Build Status PyPI version

Connected Components 3D

Implementation of connected components in three dimensions using a 26, 18, or 6 connected neighborhood. This package uses a 3D variant of the two pass method by Rosenfeld and Pflatz augmented with Union-Find and a decision tree based on the 2D 8-connected work of Wu, Otoo, and Suzuki. This implementation is compatible with images containing many different labels, not just binary images. It can be used with 2D or 3D images.

I wrote this package because I was working on densely labeled 3D biomedical images of brain tissue (e.g. 512x512x512 voxels). Other off the shelf implementations I reviewed were limited to binary images. This rendered these other packages too slow for my use case as it required masking each label and running the connected components algorithm once each time. For reference, there are often between hundreds to thousands of labels in a given volume. The benefit of this package is that it labels all connected components in one shot, improving performance by one or more orders of magnitude.

Check out benchmarks to see a comparison with SciPy on a few different tasks.

Python pip Installaction

If compatible binaries are available for your platform, installation is particularly simple.

pip install connected-components-3d

If compatible binaries are not available, you can install from source as follows.

Requires a C++ compiler.

pip install numpy
pip install connected-components-3d --no-binary :all:

Occasionally, you may appear to successfully install cc3d, but on import you'll see an error that includes: numpy.ufunc size changed, may indicate binary incompatibility. cc3d was compiled against numpy 1.16+ and unfortunately, there was a backwards incompatibilty between numpy 1.15 and 1.16. You can either try upgrading numpy or compiling from source in this case.

Python Manual Installation

Requires a C++ compiler.

pip install -r requirements.txt
python setup.py develop

Python Use

import cc3d
import numpy as np

labels_in = np.ones((512, 512, 512), dtype=np.int32)
labels_out = cc3d.connected_components(labels_in) # 26-connected

connectivity = 6 # only 26, 18, and 6 are allowed
labels_out = cc3d.connected_components(labels_in, connectivity=connectivity)

# You can adjust the bit width of the output to accomodate
# different expected image statistics with memory usage tradeoffs.
# uint16, uint32 (default), and uint64 are supported.
labels_out = cc3d.connected_components(labels_in, out_dtype=np.uint16)

# You can extract individual components like so:
N = np.max(labels_out)
for segid in range(1, N+1):
  extracted_image = labels_out * (labels_out == segid)
  process(extracted_image)

# We also include a region adjacency graph function 
# that returns a set of undirected edges. It is not optimized 
# (70-80x slower than connected_components) but it could be improved.
graph = cc3d.region_graph(labels_out, connectivity=connectivity) 

If you know approximately how many labels you are going to generate, you can save some memory by specifying a number a safety factor above that range. The max label ID in your input labels must be less than max_labels.

labels_out = connected_components(labels_in, max_labels=20000)

Note: C and Fortran order arrays will be processed in row major and column major order respectively, so the numbering of labels will be "transposed". The scare quotes are there because the dimensions of the array will not change.

C++ Use

#include "cc3d.hpp"

// 3d array represented as 1d array
int* labels = new int[512*512*512](); 

uint32_t* cc_labels = cc3d::connected_components3d<int>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512
);

// The default template parameter for output type is uint32_t
uint64_t* cc_labels = cc3d::connected_components3d<int, uint64_t>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512
);

uint16_t* cc_labels = cc3d::connected_components3d<int, uint16_t>(
  labels, /*sx=*/512, /*sy=*/512, /*sz=*/512, 
  /*connectivity=*/18 // default is 26 connected
);

Algorithm Description

The algorithm contained in this package is an elaboration into 3D images of the 2D image connected components algorithm described by Rosenfeld and Pflatz (RP) in 1968 [1] (which is well illustrated by this youtube video) using an equivalency list implemented as Tarjan's Union-Find disjoint set with path compression and balancing [2] and augmented with a decision tree based on work by Wu, Otoo, and Suzuki (WOS). [3] The description below describes the 26-connected algorithm, but once you understand it, deriving 18 and 6 are simple.

First Principles in 2D

In RP's 4-connected two-pass method for binary 2D images, the algorithm raster scans and every time it first encounters a foreground pixel (the pixels to its top and left are background), it marks it with a new label. If there is a preexisting label in its neighborhood, it uses that label instead. Whenever two labels are adjacent, it records they are equivalent so that they can be relabeled consistently in the second pass. This equivalency table can be constructed in several ways, but some popular approaches are Union-Find with path compression with balancing by rank and Selkow's algorithm (which can avoid pipeline stalls). [4] However, Selkow's algorithm is designed for two trees of depth two, appropriate for binary images. We would like to process multiple labels at the same time, making Union-Find preferable.

In the second pass, the pixels are relabeled using the equivalency table. Union-Find establishes one label as the root label of a tree, and the root is considered the representative label. Each pixel is then labeled with the representative label. Union-Find is therefore appropriate for representing disjoint sets. Path compression with balancing radically reduces the height of the tree, which accelerates the second pass.

WOS approached the problem of accelerating 8-connected 2D connected components on binary images. 8-connected labeling is achieved by extending RP's forward pass mask to the top left and top right corner pixels. In Union-Find based connected components algorithms, the unify step in the first pass is the most expensive step. WOS showed how to optimize away a large fraction of these calls using a decision tree that takes advantage of local topology. For example, since the top-center neighbor of the current pixel is also adjacent to the other mask elements, all of which have already been processed by virtue of the raster scan direction, if it is present it is sufficient to copy its value and move on. If it is absent, pick one of the remaining foreground pixels, copy their value, and use unify for the mask element on the right as it is now known to be non-neighboring with the left hand side. WOS's algorithm continues in this fashion until a match is found or all mask elements are processed at which point a new label is created.

For several years, this algorithm was the world's fastest, though it has been superceded by a newer work that exchanges the static decision tree for a dynamic one or precalculated generated one amongst other improvements. However, WOS's work is significant for both its simplicity and speed and thus serves as the inspiration for this library.

Extending to 3D

The approach presented below is very similar to that of Sutheebanjard [6]. To move to a 3D 26-connected neighborhood, the mask must be extended into three dimensions in order to connect neighboring planes. Observe that the 8-connected mask covers the trailing half of the neighborhood (the part that will have been already processed) such that the current pixel can rely on those labels. Thus the mask for the 26-connected neighborhood covers only two out of three potential planes: the entire lower plane (nine voxels), and a mask identical to WOS's (four voxels) on the current plane. While some further optimizations are possible, to begin, the problem can be conceptually decomposed into two parts: establishing a 9-connected link to the bottom plane and then an 8-connected link to the current plane. This works because the current pixel functions as a hub that transmits the connection information from the 9-connected step to the 8-connected step.

Fig. 1: Mask for an 8-connected plane. If J,K,L, and M are all eliminated, only N remains and a new label is assigned.

j k l
m n .
. . .

The very first Z plane (Z=0) the algorithm runs against is special: the edge effect omits the bottom plane of the mask. Therefore, as the remaining mask is only comprosed of the 8-connected 2D mask, after this pass, the bottom of the image is 8-connected. At Z=1, the 9-connected part of the mask kicks in, forming connections to Z=0, making the current plane now (8 + 9) 17-connected. At Z=2, the 9-connected bottom mask now forms connections from Z=1 to Z=2 on the top, making Z=1 (17 + 9) 26-connected. By induction, when this process proceeds to completion it results in a 26-connected labeling of the volume.

Following inspiration from WOS, we construct a decision tree on the densely labeled bottom plane that minimizes the number of unifications we need to perform.

Fig 2. The mask for the lower plane in 3D.

a b c
d e f
g h i

As e is connected to all other voxels, if present, it can simply be copied. If e is absent, b and h fully cover the mask. If b is absent, h, a, c comprise a covering. If h is absent, b, g, i are one. Below is a list of coverings such that each proceeding entry in the list assumes the first letters in the entries above are background.

  1. e
  2. b, (h | g, i)
  3. h, a, c
  4. d, (f | c, i)
  5. f, g, a
  6. a, c, g, i
  7. c, g, i
  8. g, i
  9. i

The decision tree is then constructed such that each of these coverings will be evaluated using the fewest unifications possible. It's possible to further optimize this by noting that e and b are both fully connected to the upper 2D mask. Therefore, if either of them are present, we can skip the 8-connected unification step. It's also possible to try the DF covering first if B is background, which would save one unification versus HAC given even statistics, but it seems to be slightly slower on the dataset I attempted. To move from binary data to multilabel data, I simply replaced tests for foreground and background with tests for matching labels.

In order to make a reasonably fast implementation, I implemented union-find with path compression. I conservatively used an IDs array qual to the size of the image for the union-find data structure instead of a sparse map. The union-find data structure plus the output labels means the memory consumption will be input + output + rank + equivalences. If your input labels are 32-bit, the memory usage will be 4x the input size. This becomes more problematic when 64-bit labels are used, but if you know something about your data, you can decrease the size of the union-find data structure. I previously used union-by-size but for some reason it merely reduced performance and increased memory usage so it was removed.

For more information on the history of connected components algorithms, and an even faster approach for 2D 8-connected components, consult Grana et al's paper on Block Based Decision Trees. [5]

References

  1. A. Rosenfeld and J. Pfaltz. "Sequential Operations in Digital Picture Processing". Journal of the ACM. Vol. 13, Issue 4, Oct. 1966, Pg. 471-494. doi: 10.1145/321356.321357 (link)
  2. R. E. Tarjan. "Efficiency of a good but not linear set union algorithm". Journal of the ACM, 22:215-225, 1975. (link)
  3. K. Wu, E. Otoo, K. Suzuki. "Two Strategies to Speed up Connected Component Labeling Algorithms". Lawrence Berkely National Laboratory. LBNL-29102, 2005. (link)
  4. S. Selkow. "The Tree-to-Tree Editing Problem". Information Processing Letters. Vol. 6, No. 6. June 1977. doi: 10.1016/0020-0190(77)90064-3 (link)
  5. C. Grana, D. Borghesani, R. Cucchiara. "Optimized Block-based Connected Components Labeling with Decision Trees". IEEE Transactions on Image Porcessing. Vol. 19, Iss. 6. June 2010. doi: 10.1109/TIP.2010.2044963 (link)
  6. P. Sutheebanjard. "Decision Tree for 3-D Connected Components Labeling". Proc. 2012 International Symposium on Information Technology in Medicine and EEducation. doi: 10.1109/ITiME.2012.6291402 (link)

Project details


Download files

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

Source Distribution

connected-components-3d-1.6.0.tar.gz (393.6 kB view details)

Uploaded Source

Built Distributions

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

connected_components_3d-1.6.0-cp38-cp38-win_amd64.whl (200.0 kB view details)

Uploaded CPython 3.8Windows x86-64

connected_components_3d-1.6.0-cp38-cp38-macosx_10_9_x86_64.whl (199.1 kB view details)

Uploaded CPython 3.8macOS 10.9+ x86-64

connected_components_3d-1.6.0-cp37-cp37m-win_amd64.whl (205.3 kB view details)

Uploaded CPython 3.7mWindows x86-64

connected_components_3d-1.6.0-cp37-cp37m-macosx_10_9_x86_64.whl (198.0 kB view details)

Uploaded CPython 3.7mmacOS 10.9+ x86-64

connected_components_3d-1.6.0-cp36-cp36m-win_amd64.whl (205.3 kB view details)

Uploaded CPython 3.6mWindows x86-64

connected_components_3d-1.6.0-cp36-cp36m-macosx_10_9_x86_64.whl (197.9 kB view details)

Uploaded CPython 3.6mmacOS 10.9+ x86-64

connected_components_3d-1.6.0-cp35-cp35m-macosx_10_6_intel.whl (361.0 kB view details)

Uploaded CPython 3.5mmacOS 10.6+ Intel (x86-64, i386)

connected_components_3d-1.6.0-cp27-cp27m-macosx_10_14_intel.whl (197.2 kB view details)

Uploaded CPython 2.7mmacOS 10.14+ Intel (x86-64, i386)

File details

Details for the file connected-components-3d-1.6.0.tar.gz.

File metadata

  • Download URL: connected-components-3d-1.6.0.tar.gz
  • Upload date:
  • Size: 393.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.29.1 CPython/3.6.6

File hashes

Hashes for connected-components-3d-1.6.0.tar.gz
Algorithm Hash digest
SHA256 cfbe1596203b5fac60fe2ea6ad047cd98a90dd28a2da6e9cfcf53161a2e519fc
MD5 b0ba3ab9334aeeaa31544a2d2a29ca11
BLAKE2b-256 5d59626ea56ea0fa8698e8cbf1f5f9cc5a36ae5d4e640dd31eddf37a57e45998

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: connected_components_3d-1.6.0-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 200.0 kB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/28.8.0 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.5.4

File hashes

Hashes for connected_components_3d-1.6.0-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 4f778c71e63727794340c64c7c81a7a2c67874012e2ed5b24319adef05d9725c
MD5 4715ca308eab286998e55f2b7eb186e2
BLAKE2b-256 dfd590db9c3a322adb086ebc3fd035cfdea2dcdf1a206ef6fc70e5721747d807

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp38-cp38-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-1.6.0-cp38-cp38-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 db9197c676baa972aa4f82fe5f9b21d8995306663ef6a4958ca1cae682e3d83d
MD5 e2b902fae188df0ef0b601332bf4b998
BLAKE2b-256 3ecf2ae5bf8774aedcfb325d3aef5457fd5fe5048a77244450e22ee25201aa7a

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

  • Download URL: connected_components_3d-1.6.0-cp38-cp38-macosx_10_9_x86_64.whl
  • Upload date:
  • Size: 199.1 kB
  • Tags: CPython 3.8, macOS 10.9+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2

File hashes

Hashes for connected_components_3d-1.6.0-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a441d52522b1941423ed0a6fa4ece18a9f511550f0e881434b6b701b462b124f
MD5 7b3fc3d4430a11cb135958995df93c5c
BLAKE2b-256 8f97023630075e7339aabc8d91424e6a9c339c7363912fd0a03bdf348bd81951

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: connected_components_3d-1.6.0-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 205.3 kB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/28.8.0 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.5.4

File hashes

Hashes for connected_components_3d-1.6.0-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 baa740c95b1cb198becd48cf6dda4c3e2319c020cf72088d91863349f7856b7c
MD5 886a89b99ceb9d1ae2c0361a85a86063
BLAKE2b-256 327745690c7824202f4a9aa1ac50a81d25cd3aeae227088b9d8b738f2a5a2860

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp37-cp37m-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-1.6.0-cp37-cp37m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 e9a1020fdf039cb90644cc8fba78a76e96bf3a48283e63249de392c38a631910
MD5 4962942e12b258f8f1e3b7fd5e9a670c
BLAKE2b-256 a4e2928eff96ed2526f37cc3386f9c3cf07c27c56e83b17b19c7c66c4765ea12

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp37-cp37m-macosx_10_9_x86_64.whl.

File metadata

  • Download URL: connected_components_3d-1.6.0-cp37-cp37m-macosx_10_9_x86_64.whl
  • Upload date:
  • Size: 198.0 kB
  • Tags: CPython 3.7m, macOS 10.9+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2

File hashes

Hashes for connected_components_3d-1.6.0-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 67a0f8400f4add09a145750514e5e6e7ab0188d9e67bf87400a7324c4ff91c27
MD5 125d9f46d8ce576ebb5a4d6f2ee2081d
BLAKE2b-256 d9f33deb243cb9e9300d0da32e1e020f79c7f0bb9368b057394773a5d15e1fba

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp36-cp36m-win_amd64.whl.

File metadata

  • Download URL: connected_components_3d-1.6.0-cp36-cp36m-win_amd64.whl
  • Upload date:
  • Size: 205.3 kB
  • Tags: CPython 3.6m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/28.8.0 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.5.4

File hashes

Hashes for connected_components_3d-1.6.0-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 8d74818e93083b35ca44b7b57c51d4293a8f76c3b0a21d759766a0eeede90dde
MD5 7a02f1f5a8b2b3eccc4f289b084d3815
BLAKE2b-256 3a4178e1ebdefad49328f4512d4cf18d086c13f63e54c229667998033842e936

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp36-cp36m-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-1.6.0-cp36-cp36m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 83fb887a886eada086261fb02065398f2600d5e3f9fdf18cc4692fc425fabeb4
MD5 8380ff220c8c69b187e5480a474df4a4
BLAKE2b-256 8c7122f4f5e683ee7aef35035b35aaedc2ca79bc0730b2b9f9e1632d7d20902e

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp36-cp36m-macosx_10_9_x86_64.whl.

File metadata

  • Download URL: connected_components_3d-1.6.0-cp36-cp36m-macosx_10_9_x86_64.whl
  • Upload date:
  • Size: 197.9 kB
  • Tags: CPython 3.6m, macOS 10.9+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2

File hashes

Hashes for connected_components_3d-1.6.0-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 905fb21a930d8fe1c44b52d443df8639b5f918c6b6063bdd85a7e75af6ab98db
MD5 94171de8931468f5f3c516b1cb47f746
BLAKE2b-256 39d23ea12f05c9408f76865c37d8bf32bf03cd7e5456ca891b15d80e06c5ddce

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp35-cp35m-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-1.6.0-cp35-cp35m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 b208b2a92357d7c727d34e2f9cd5636059c51d355cd4fe8eade080025c116b0d
MD5 6c7bc3d539bf921ad28fe62efc3600bb
BLAKE2b-256 160f968ba9580c4920926d0044b0376b91337490b8e3053e73fdb24402cf3421

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp35-cp35m-macosx_10_6_intel.whl.

File metadata

  • Download URL: connected_components_3d-1.6.0-cp35-cp35m-macosx_10_6_intel.whl
  • Upload date:
  • Size: 361.0 kB
  • Tags: CPython 3.5m, macOS 10.6+ Intel (x86-64, i386)
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2

File hashes

Hashes for connected_components_3d-1.6.0-cp35-cp35m-macosx_10_6_intel.whl
Algorithm Hash digest
SHA256 d35432987a7551855ae50bf0043bfdf6ece76fcdf0f8f909ba68f38b1fa701a7
MD5 2c2b50b97ce994070e05c12fec445610
BLAKE2b-256 d97be790c38ba10ed62dfeb6d625a898d6840a40188d3430e39df9a1c0956359

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp34-cp34m-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-1.6.0-cp34-cp34m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 d47bb25cba2afa886c0295a7117f534d9afa61bb5827339f157dd74eb6c7ef16
MD5 0c68ec55555f6fd1b16fa78466bb4708
BLAKE2b-256 693d855b0006eab1775c30e239a10fc7781a85038ce0a58f4c95272e5b233eb8

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp27-cp27m-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for connected_components_3d-1.6.0-cp27-cp27m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 bd7a1d5a13d5892b0c0c9f7431a20b7f76765c8b586c71d5d1c8859d1790d7ed
MD5 1b9463b2a98269e1a091f988c1f69ab1
BLAKE2b-256 e9917eae1fa3f00471bd7d00ed2678d141e9bbd42deab30874365ba2271d9926

See more details on using hashes here.

File details

Details for the file connected_components_3d-1.6.0-cp27-cp27m-macosx_10_14_intel.whl.

File metadata

  • Download URL: connected_components_3d-1.6.0-cp27-cp27m-macosx_10_14_intel.whl
  • Upload date:
  • Size: 197.2 kB
  • Tags: CPython 2.7m, macOS 10.14+ Intel (x86-64, i386)
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.2

File hashes

Hashes for connected_components_3d-1.6.0-cp27-cp27m-macosx_10_14_intel.whl
Algorithm Hash digest
SHA256 bc860f6a3a7b12adf6f7889f7e588a9f473eeb35a554d5cba4b7ca962f0327f2
MD5 d3a72b87374c79c683baaa94e0757341
BLAKE2b-256 c8e991cd0c9cdc30949086d7a4d15b3da1fec278879d23a588b67ae6cbfb272c

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 Pingdom Monitoring Sentry Error logging StatusPage Status page