Package: fastremap
fastremapRenumber and relabel Numpy arrays at C++ speed and physically convert rectangular Numpy arrays between C and Fortran order using an in-place transposition.importfastremapuniq,cts=fastremap.unique(labels,return_counts=True)# may be much faster than np.uniquelabels,remapping=fastremap.renumber(labels,in_place=True)# relabel values from 1 and refit data typeptc=fastremap.point_cloud(labels)# dict of coordinates by labellabels=fastremap.refit(labels)# resize the data type of the array to fit extremalabels=fastremap.refit(labels,value=-35)# resize the data type to fit the value provided# remap all occurances of 1 -> 2labels=fastremap.remap(labels,{1:2},preserve_missing_labels=True,in_place=True)labels=fastremap.mask(labels,[1,5,13])# set all occurances of 1,5,13 to 0labels=fastremap.mask_except(labels,[1,5,13])# set all labels except 1,5,13 to 0mapping=fastremap.component_map([1,2,3,4],[5,5,6,7])# { 1: 5, 2: 5, 3: 6, 4: 7 }mapping=fastremap.inverse_component_map([1,2,1,3],[4,4,5,6])# { 1: [ 4, 5 ], 2: [ 4 ], 3: [ 6 ] }fastremap.transpose(labels)# physically transpose labels in-placefastremap.ascontiguousarray(labels)# try to perform a physical in-place transposition to C orderfastremap.asfortranarray(labels)# try to perform a physical in-place transposition to F orderminval,maxval=fastremap.minmax(labels)# faster version of (np.min(labels), np.max(labels))# computes number of matching adjacent pixel pairs in an imagenum_pairs=fastremap.pixel_pairs(labels)n_foreground=fastremap.foreground(labels)# number of nonzero voxels# computes the cutout.tobytes(order) of each chunk and returns# the binaries indexed by fortran order in the order specified (C or F)# If the input image is F contiguous and F is requested, or C and C order,# and the image is larger than a single chunk, this will be significantly# faster than iterating and using tobytes.binaries=fastremap.tobytes(labels,(64,64,64),order="F")All Available Functionsunique:Faster implementation ofnp.unique.renumber:Relabel array from 1 to N which can often use smaller datatypes.remap:Custom relabeling of values in an array from a dictionary.refit:Resize the data type of an array to the smallest that can contain the most extreme values in it.mask:Zero out labels in an array specified by a given list.mask_except: Zero out all labels except those specified in a given list.component_map: Extract an int-to-int dictionary mapping of labels from one image containing component labels to another parent labels.inverse_component_map: Extract an int-to-list-of-ints dictionary mapping from an image containing groups of components to an image containing the components.remap_from_array:Same as remap, but the map is an array where the key is the array index and the value is the value.remap_from_array_kv:Same as remap, but the map consists of two equal sized arrays, the first containing keys, the second containing values.asfortranarray:Perform an in-place matrix transposition for rectangular arrays if memory is contiguous, standard numpy otherwise.ascontiguousarray:Perform an in-place matrix transposition for rectangular arrays if memory is contiguous, standard numpy algorithm otherwise.minmax:Compute the min and max of an array in one pass.pixel_pairs:Computes the number of adjacent matching memory locations in an image. A quick heuristic for understanding if the image statistics are roughly similar to a connectomics segmentation.foreground:Count the number of non-zero voxels rapidly.point_cloud:Get the X,Y,Z locations of each foreground voxel grouped by label.tobytes: Compute the tobytes of an image divided into a grid and return the resultant binaries indexed by their gridpoint in fortran order with the binary in the order requested (C or F).pipInstallationpipinstallfastremapIf not, a C++ compiler is required.pipinstallnumpy
pipinstallfastremap--no-binary:all:Manual InstallationA C++ compiler is required.sudoapt-getinstallg++python3-devmkvirtualenv-ppython3fastremap
pipinstallnumpy# Choose one:pythonsetup.pydeveloppythonsetup.pyinstallThe Problem of RemappingPython loops are slow, so Numpy is often used to perform remapping on large arrays (hundreds of megabytes or gigabytes). In order to efficiently remap an array in Numpy you need a key-value array where the index is the key and the value is the contents of that index.importnumpyasnporiginal=np.array([1,3,5,5,10])remap=np.array([0,-5,0,6,0,0,2,0,0,0,-100])# Keys:            0   1  2  3  4  5  6  7  8  9    10remapped=remap[original]>>>[-5,6,2,2,-100]If there are 32 or 64 bit labels in the array, this becomes impractical as the size of the array can grow larger than RAM. Therefore, it would be helpful to be able to perform this mapping using a C speed loop. Numba can be used for this in some circumstances. However, this library provides an alternative.importnumpyasnpimportfastremapmappings={1:100,2:200,-3:7,}arr=np.array([5,1,2,-5,-3,10,6])# Custom remapping of -3, 5, and 6 leaving the rest alonearr=fastremap.remap(arr,mappings,preserve_missing_labels=True)# result: [ 5, 100, 200, -5, 7, 10, 6 ]The Problem of RenumberingSometimes a 64-bit array contains values that could be represented by an 8-bit array. However, similarly to the remapping problem, Python loops can be too slow to do this. Numpy doesn't provide a convenient way to do it either. Therefore this library provides an alternative solution.importfastremapimportnumpyasnparr=np.array([283732875,439238823,283732875,182812404,0],dtype=np.int64)arr,remapping=fastremap.renumber(arr,preserve_zero=True)# Returns uint8 array>>>arr=[1,2,1,3,0]>>>remapping={0:0,283732875:1,439238823:2,182812404:3}arr,remapping=fastremap.renumber(arr,preserve_zero=False)# Returns uint8 array>>>arr=[1,2,1,3,4]>>>remapping={0:4,283732875:1,439238823:2,182812404:3}arr,remapping=fastremap.renumber(arr,preserve_zero=False,in_place=True)# Mutate arr to use less memory>>>arr=[1,2,1,3,4]>>>remapping={0:4,283732875:1,439238823:2,182812404:3}The Problem of In-Place TranspositionWhen transitioning between different media, e.g. CPU to GPU, CPU to Network, CPU to disk, it's often necessary to physically transpose multi-dimensional arrays to reformat as C or Fortran order. Tranposing matrices is also a common action in linear algebra, but often you can get away with just changing the strides.An out-of-place transposition is easy to write, and often faster, but it will spike peak memory consumption. This library grants the user the option of performing an in-place transposition which trades CPU time for peak memory usage. In the special case of square or cubic arrays, the in-place transpisition is both lower memory and faster.fastremap.asfortranarray:Same as np.asfortranarray but will perform the transposition in-place for 1, 2, 3, and 4D arrays. 2D and 3D square matrices are faster to process than with Numpy.fastremap.ascontiguousarray:Same as np.ascontiguousarray but will perform the transposition in-place for 1, 2, 3, and 4D arrays. 2D and 3D square matrices are faster to process than with Numpy.importfastremapimportnumpyasnparr=np.ones((512,512,512),dtype=np.float32)arr=fastremap.asfortranarray(x)arr=np.ones((512,512,512),dtype=np.float32,order='F')arr=fastremap.ascontiguousarray(x)C++ UsageThe in-place matrix transposition is implemented in ipt.hpp. If you're working in C++, you can also use it directly like so:#include"ipt.hpp"intmain(){intsx=128;intsy=124;intsz=103;intsw=3;auto*arr=....;// All primitive number types supported// The array will be modified in place,// so these functions are void type.ipt::ipt<int>(arr,sx,sy);// 2Dipt::ipt<float>(arr,sx,sy,sz);// 3Dipt::ipt<double>(arr,sx,sy,sz,sw);// 4Dreturn0;}--Made with <3