I'm trying to implement an active mask code derived from Active mask segmentation for the cell-volume computation and golgi-body segmentation of hela cell images, Srinivasa et al 2008.

I have found a code that will allow me to do this, however, there is one section of the code that is giving me errors and I don't know why. Here is the section of the code:

def _converge(P, R, b, max_iters_converge=1000):
    Pm = numpy.empty(P.shape, numpy.float32)  # Pre-allocate: saves time
    argmax = numpy.zeros_like(P)
    maxval = numpy.zeros(P.shape, numpy.float32)
    for i in range(max_iters_converge):
        maxval *= 0
        maxval -= 1e8
        for m in range(int(P.max()) + 1):
            Pm[:, :] = (P == m)
            Pm = ndimage.gaussian_filter(Pm, b) + R[m]  
 # Pm=ndimage.convolve(Pm,numpy.ones((2*b+1,2*b+1)))+R[m]
            argmax[maxval < Pm] = m
            maxval = maxval * (argmax != m) + (argmax == m) * Pm
        if (P == argmax).all(): break
        P = argmax.copy()
    mis = defaultdict(range(1, P.max() + 1).__iter__().__next__())
    mis[0] = 0  # set 0 to 0, because it is special
    for i in range(P.size):
        P.flat[i] = mis[P.flat[i]]
    return P

The area that is giving me the most problem is the:

mis = defaultdict(range(1, P.max() + 1).__iter__().__next__())

Originally the code was written for Python 2.4 but I made some changes so that it will work on Python 3.6, but I don't really understand what the defaultdict is used for.

Here is a link to the full original source file: active mask


1 Answer 1


The defaultdict in this case is meant to return the next increasing integer each time a new element is encountered in P.flat(). But to also return the same integer each time that same element is found again. You should have encountered the error:

TypeError: first argument must be callable or None

defaultdict expects a callable. It will call the passed in function each time there is a lookup miss, and set the dict to that value. To fix that error you need to remove the () from the __next__() to leave:

mis = defaultdict(range(1, P.max() + 1).__iter__().__next__)

However this is overly complicated for what it is doing, and can be simplified a bit by recognizing that there is no reason to have the upper limit in the range, it is just an increasing integer which can be done with itertools.count() liike:

import itertools as it
mis = defaultdict(it.count(1).__next__)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.