Example #1
0
 def setUpClass(cls):
     cls.size = validate_tuple(cls.size, cls.ndim)
     if not hasattr(cls, 'diameter'):
         cls.diameter = tuple([int(s * 4) for s in cls.size])
     else:
         cls.diameter = validate_tuple(cls.diameter, cls.ndim)
     cls.separation = tuple([d * 2 for d in cls.diameter])
     cls.radius = tuple([int(d // 2) for d in cls.diameter])
     cls.isotropic = np.all([cls.diameter[1:] == cls.diameter[:-1]])
     cls.pos_columns = ['z', 'y', 'x'][-cls.ndim:]
     cls.pos_columns_err = [col + '_std' for col in cls.pos_columns]
     if cls.isotropic:
         cls.size_columns = ['size']
     else:
         cls.size_columns = ['size_z', 'size_y', 'size_x'][-cls.ndim:]
     cls.names = cls.pos_columns + ['signal'] + cls.size_columns
     # cls.rtol = [None] * len(cls.im.pos_columns)
     # cls.atol = [0.1] * len(cls.im.pos_columns)
     cls.bounds = dict()
     if not hasattr(cls, 'param_mode'):
         cls.param_mode = dict(signal='var', size='const')
     if not hasattr(cls, 'feat_kwargs'):
         cls.feat_kwargs = dict()
     if not hasattr(cls, 'param_val'):
         cls.param_val = dict()
Example #2
0
 def __init__(self, shape, size, dtype=np.uint8, saturation=None,
              hard_radius=None, signal=None, noise=0,
              feat_func=feat_gauss, **feat_kwargs):
     self.ndim = len(shape)
     self.shape = shape
     self.dtype = dtype
     self.image = Frame(np.zeros(shape, dtype=dtype))
     self.size = validate_tuple(size, self.ndim)
     self.isotropic = np.all([self.size[1:] == self.size[:-1]])
     self.feat_func = feat_func
     self.feat_kwargs = feat_kwargs
     self.noise = noise
     if saturation is None and np.issubdtype(dtype, np.integer):
         self.saturation = np.iinfo(dtype).max
     elif saturation is None and np.issubdtype(dtype, np.float):
         self.saturation = 1
     else:
         self.saturation = saturation
     if signal is None:
         self.signal = self.saturation
     else:
         self.signal = signal
     self.center = tuple([s // 2 for s in shape])
     self.hard_radius = hard_radius
     self._coords = []
     self.pos_columns = ['z', 'y', 'x'][-self.ndim:]
     if self.isotropic:
         self.size_columns = ['size']
     else:
         self.size_columns = ['size_z', 'size_y', 'size_x'][-self.ndim:]
Example #3
0
def draw_array(N, size, separation=None, ndim=2, **kwargs):
    """ Generates an image with an array of features. Each feature has a random
    offset of +- 0.5 pixel.

    Parameters
    ----------
    N : int
        the number of features
    size : number
        the size of the feature (meaning depends on feature, for feat_gauss,
        it is the radius of gyration)
    separation : number or tuple
        the desired separation between features
    kwargs : keyword arguments are passed to draw_spots

    See also
    --------
    draw_spots
    draw_feature
    """
    size = validate_tuple(size, ndim)
    if separation is None:
        separation = tuple([sz * 8 for sz in size])
    margin = separation
    Nsqrt = int(N**(1 / ndim) + 0.9999)
    pos = np.meshgrid(*[np.arange(0, s * Nsqrt, s) for s in separation],
                      indexing='ij')
    pos = np.array([p.ravel() for p in pos], dtype=float).T[:N] + margin
    pos += (np.random.random(pos.shape) - 0.5)  #randomize subpixel location
    shape = tuple(np.max(pos, axis=0).astype(int) + margin)
    return pos, draw_spots(shape, pos, size, **kwargs)
Example #4
0
def draw_array(N, diameter, separation=None, ndim=2, **kwargs):
    """ Generates an image with an array of features. Each feature has a random
    offset of +- 0.5 pixel.

    Parameters
    ----------
    N : int
        the number of features
    diameter : number or tuple
        the sizes of the box that will be used per feature. The actual feature
        'size' is determined by feat_func and kwargs given to feat_func.
    separation : number or tuple
        the desired separation between features
    kwargs : see draw_spots

    See also
    --------
    draw_spots
    """
    diameter = validate_tuple(diameter, ndim)
    if separation is None:
        separation = tuple([d * 2 for d in diameter])
    margin = separation
    Nsqrt = int(N**(1/ndim) + 0.9999)
    pos = np.meshgrid(*[np.arange(0, s * Nsqrt, s) for s in separation],
                      indexing='ij')
    pos = np.array([p.ravel() for p in pos], dtype=np.float).T[:N] + margin
    pos += (np.random.random(pos.shape) - 0.5)  #randomize subpixel location
    shape = tuple(np.max(pos, axis=0).astype(np.int) + margin)
    return pos, draw_spots(shape, pos, diameter, **kwargs)
Example #5
0
def draw_array(N, size, separation=None, ndim=2, **kwargs):
    """ Generates an image with an array of features. Each feature has a random
    offset of +- 0.5 pixel.

    Parameters
    ----------
    N : int
        the number of features
    size : number
        the size of the feature (meaning depends on feature, for feat_gauss,
        it is the radius of gyration)
    separation : number or tuple
        the desired separation between features
    kwargs : keyword arguments are passed to draw_spots

    See also
    --------
    draw_spots
    draw_feature
    """
    size = validate_tuple(size, ndim)
    if separation is None:
        separation = tuple([sz * 8 for sz in size])
    margin = separation
    Nsqrt = int(N**(1/ndim) + 0.9999)
    pos = np.meshgrid(*[np.arange(0, s * Nsqrt, s) for s in separation],
                      indexing='ij')
    pos = np.array([p.ravel() for p in pos], dtype=np.float).T[:N] + margin
    pos += (np.random.random(pos.shape) - 0.5)  #randomize subpixel location
    shape = tuple(np.max(pos, axis=0).astype(np.int) + margin)
    return pos, draw_spots(shape, pos, size, **kwargs)
Example #6
0
def gen_random_locations(shape, count, margin=0):
    """ Generates `count` number of positions within `shape`. If a `margin` is
    given, positions will be inside this margin. Margin may be tuple-valued.
    """
    margin = validate_tuple(margin, len(shape))
    np.random.seed(0)
    pos = [np.random.uniform(round(m), round(s - m), count)
           for (s, m) in zip(shape, margin)]
    return np.array(pos).T
Example #7
0
def draw_feature(image,
                 position,
                 diameter,
                 max_value=None,
                 feat_func=feat_gauss,
                 ecc=None,
                 **kwargs):
    """ Draws a radial symmetric feature and adds it to the image at given
    position. The given function will be evaluated at each pixel coordinate,
    no averaging or convolution is done.

    Parameters
    ----------
    image : ndarray
        image to draw features on
    position : iterable
        coordinates of feature position
    diameter : number
        defines the box that will be drawn on
    max_value : number
        maximum feature value. should be much less than the max value of the
        image dtype, to avoid pixel wrapping at overlapping features
    feat_func : function. Default: feat_gauss
        function f(r) that takes an ndarray of radius values
        and returns intensity values <= 1
    ecc : positive number, optional
        eccentricity of feature, defined only in 2D. Identical to setting
        diameter to (diameter / (1 - ecc), diameter * (1 - ecc))
    kwargs : keyword arguments are passed to feat_func
    """
    if len(position) != image.ndim:
        raise ValueError("Number of position coordinates should match image"
                         " dimensionality.")
    diameter = validate_tuple(diameter, image.ndim)
    if ecc is not None:
        if len(diameter) != 2:
            raise ValueError("Eccentricity is only defined in 2 dimensions")
        if diameter[0] != diameter[1]:
            raise ValueError("Diameter is already anisotropic; eccentricity is"
                             " not defined.")
        diameter = (diameter[0] / (1 - ecc), diameter[1] * (1 - ecc))
    radius = tuple([d / 2 for d in diameter])
    if max_value is None:
        max_value = np.iinfo(image.dtype).max - 3
    rect = []
    vectors = []
    for (c, r, lim) in zip(position, radius, image.shape):
        if (c >= lim) or (c < 0):
            raise ValueError("Position outside of image.")
        lower_bound = max(int(np.floor(c - r)), 0)
        upper_bound = min(int(np.ceil(c + r + 1)), lim)
        rect.append(slice(lower_bound, upper_bound))
        vectors.append(np.arange(lower_bound - c, upper_bound - c) / r)
    coords = np.meshgrid(*vectors, indexing='ij', sparse=True)
    r = np.sqrt(np.sum(np.array(coords)**2, axis=0))
    spot = max_value * feat_func(r, **kwargs)
    image[rect] += spot.astype(image.dtype)
Example #8
0
def gen_random_locations(shape, count, margin=0):
    """ Generates `count` number of positions within `shape`. If a `margin` is
    given, positions will be inside this margin. Margin may be tuple-valued.
    """
    margin = validate_tuple(margin, len(shape))
    np.random.seed(0)
    pos = [np.random.randint(round(m), round(s - m), count)
           for (s, m) in zip(shape, margin)]
    return np.array(pos).T
Example #9
0
def gen_connected_locations(shape, count, separation, margin=0):
    """ Generates `count` number of positions within `shape` that are touching.
    If a `margin` is given, positions will be inside this margin. Margin may be
    tuple-valued.  """
    margin = validate_tuple(margin, len(shape))
    center_pos = margin + np.round(np.subtract(shape, margin) / 2.0)
    indices = np.arange(0, count, 1) - np.round(count / 2.0)
    pos = np.array(
        [np.add(center_pos, np.multiply(i, separation)) for i in indices])

    return pos
Example #10
0
def draw_feature(image, position, diameter, max_value=None,
                 feat_func=feat_gauss, ecc=None, **kwargs):
    """ Draws a radial symmetric feature and adds it to the image at given
    position. The given function will be evaluated at each pixel coordinate,
    no averaging or convolution is done.

    Parameters
    ----------
    image : ndarray
        image to draw features on
    position : iterable
        coordinates of feature position
    diameter : number
        defines the box that will be drawn on
    max_value : number
        maximum feature value. should be much less than the max value of the
        image dtype, to avoid pixel wrapping at overlapping features
    feat_func : function. Default: feat_gauss
        function f(r) that takes an ndarray of radius values
        and returns intensity values <= 1
    ecc : positive number, optional
        eccentricity of feature, defined only in 2D. Identical to setting
        diameter to (diameter / (1 - ecc), diameter * (1 - ecc))
    kwargs : keyword arguments are passed to feat_func
    """
    if len(position) != image.ndim:
        raise ValueError("Number of position coordinates should match image"
                         " dimensionality.")
    diameter = validate_tuple(diameter, image.ndim)
    if ecc is not None:
        if len(diameter) != 2:
            raise ValueError("Eccentricity is only defined in 2 dimensions")
        if diameter[0] != diameter[1]:
            raise ValueError("Diameter is already anisotropic; eccentricity is"
                             " not defined.")
        diameter = (diameter[0] / (1 - ecc), diameter[1] * (1 - ecc))
    radius = tuple([d / 2 for d in diameter])
    if max_value is None:
        max_value = np.iinfo(image.dtype).max - 3
    rect = []
    vectors = []
    for (c, r, lim) in zip(position, radius, image.shape):
        if (c >= lim) or (c < 0):
            raise ValueError("Position outside of image.")
        lower_bound = max(int(np.floor(c - r)), 0)
        upper_bound = min(int(np.ceil(c + r + 1)), lim)
        rect.append(slice(lower_bound, upper_bound))
        vectors.append(np.arange(lower_bound - c, upper_bound - c) / r)
    coords = np.meshgrid(*vectors, indexing='ij', sparse=True)
    r = np.sqrt(np.sum(np.array(coords)**2, axis=0))
    spot = max_value * feat_func(r, **kwargs)
    image[rect] += spot.astype(image.dtype)
Example #11
0
 def setUpClass(cls):
     super(RefineTsts, cls).setUpClass()
     cls.size = validate_tuple(cls.size, cls.ndim)
     if not hasattr(cls, 'diameter'):
         cls.diameter = tuple([int(s * 4) for s in cls.size])
     else:
         cls.diameter = validate_tuple(cls.diameter, cls.ndim)
     cls.separation = tuple([d * 2 for d in cls.diameter])
     cls.radius = tuple([int(d // 2) for d in cls.diameter])
     cls.isotropic = np.all([cls.diameter[1:] == cls.diameter[:-1]])
     cls.pos_columns = ['z', 'y', 'x'][-cls.ndim:]
     cls.pos_columns_err = [col + '_std' for col in cls.pos_columns]
     if cls.isotropic:
         cls.size_columns = ['size']
     else:
         cls.size_columns = ['size_z', 'size_y', 'size_x'][-cls.ndim:]
     cls.names = cls.pos_columns + ['signal'] + cls.size_columns
     cls.bounds = dict()
     if not hasattr(cls, 'param_mode'):
         cls.param_mode = dict(signal='var', size='const')
     if not hasattr(cls, 'feat_kwargs'):
         cls.feat_kwargs = dict()
     if not hasattr(cls, 'param_val'):
         cls.param_val = dict()
Example #12
0
def eliminate_overlapping_locations(f, separation):
    """ Makes sure that no position is within `separation` from each other, by
    deleting one of the that are to close to each other.
    """
    separation = validate_tuple(separation, f.shape[1])
    assert np.greater(separation, 0).all()
    # Rescale positions, so that pairs are identified below a distance of 1.
    f = f / separation
    while True:
        duplicates = cKDTree(f, 30).query_pairs(1)
        if len(duplicates) == 0:
            break
        to_drop = []
        for pair in duplicates:
            to_drop.append(pair[1])
        f = np.delete(f, to_drop, 0)
    return f * separation
Example #13
0
def eliminate_overlapping_locations(f, separation):
    """ Makes sure that no position is within `separation` from each other, by
    deleting one of the that are to close to each other.
    """
    separation = validate_tuple(separation, f.shape[1])
    assert np.greater(separation, 0).all()
    # Rescale positions, so that pairs are identified below a distance of 1.
    f = f / separation
    while True:
        duplicates = cKDTree(f, 30).query_pairs(1)
        if len(duplicates) == 0:
            break
        to_drop = []
        for pair in duplicates:
            to_drop.append(pair[1])
        f = np.delete(f, to_drop, 0)
    return f * separation
Example #14
0
 def __init__(self,
              shape,
              size,
              dtype=np.uint8,
              saturation=None,
              hard_radius=None,
              signal=None,
              noise=0,
              feat_func=feat_gauss,
              **feat_kwargs):
     self.ndim = len(shape)
     self.shape = shape
     self.dtype = dtype
     self.image = np.zeros(shape, dtype=dtype)
     if _Frame is not None:
         self.image = _Frame(self.image)
     self.size = validate_tuple(size, self.ndim)
     self.isotropic = np.all([self.size[1:] == self.size[:-1]])
     self.feat_func = feat_func
     self.feat_kwargs = feat_kwargs
     self.noise = noise
     if saturation is None and np.issubdtype(dtype, np.integer):
         self.saturation = np.iinfo(dtype).max
     elif saturation is None and np.issubdtype(dtype, np.floating):
         self.saturation = 1
     else:
         self.saturation = saturation
     if signal is None:
         self.signal = self.saturation
     else:
         self.signal = signal
     self.center = tuple([s // 2 for s in shape])
     self.hard_radius = hard_radius
     self._coords = []
     self.pos_columns = ['z', 'y', 'x'][-self.ndim:]
     if self.isotropic:
         self.size_columns = ['size']
     else:
         self.size_columns = ['size_z', 'size_y', 'size_x'][-self.ndim:]
Example #15
0
def draw_feature(image,
                 position,
                 size,
                 max_value=None,
                 feat_func='gauss',
                 ecc=None,
                 mask_diameter=None,
                 **kwargs):
    """ Draws a radial symmetric feature and adds it to the image at given
    position. The given function will be evaluated at each pixel coordinate,
    no averaging or convolution is done.

    Parameters
    ----------
    image : ndarray
        image to draw features on
    position : iterable
        coordinates of feature position
    size : number
        the size of the feature (meaning depends on feature, for feat_gauss,
        it is the radius of gyration)
    max_value : number
        maximum feature value. should be much less than the max value of the
        image dtype, to avoid pixel wrapping at overlapping features
    feat_func : {'gauss', 'disc', 'ring'} or callable
        Default: 'gauss'
        When callable is given, it should take an ndarray of radius values
        and it should return intensity values <= 1
    ecc : positive number, optional
        eccentricity of feature, defined only in 2D. Identical to setting
        diameter to (diameter / (1 - ecc), diameter * (1 - ecc))
    mask_diameter :
        defines the box that will be drawn on. Default 4 * size.
    kwargs : keyword arguments are passed to feat_func

    See also
    --------
    draw_spots
    """
    if len(position) != image.ndim:
        raise ValueError("Number of position coordinates should match image"
                         " dimensionality.")
    if not hasattr(feat_func, '__call__'):
        feat_func = feat_dict[feat_func]
    size = validate_tuple(size, image.ndim)
    if ecc is not None:
        if len(size) != 2:
            raise ValueError("Eccentricity is only defined in 2 dimensions")
        if size[0] != size[1]:
            raise ValueError("Diameter is already anisotropic; eccentricity is"
                             " not defined.")
        size = (size[0] / (1 - ecc), size[1] * (1 - ecc))
    if mask_diameter is None:
        mask_diameter = tuple([s * 4 for s in size])
    else:
        mask_diameter = validate_tuple(mask_diameter, image.ndim)
    if max_value is None:
        max_value = np.iinfo(image.dtype).max - 3
    rect = []
    vectors = []
    for (c, s, m, lim) in zip(position, size, mask_diameter, image.shape):
        if (c >= lim) or (c < 0):
            raise ValueError("Position outside of image.")
        lower_bound = max(int(np.floor(c - m / 2)), 0)
        upper_bound = min(int(np.ceil(c + m / 2 + 1)), lim)
        rect.append(slice(lower_bound, upper_bound))
        vectors.append(np.arange(lower_bound - c, upper_bound - c) / s)
    coords = np.meshgrid(*vectors, indexing='ij')
    r = np.sqrt(np.sum(np.array(coords)**2, axis=0))
    spot = max_value * feat_func(r, ndim=image.ndim, **kwargs)
    image[tuple(rect)] += spot.astype(image.dtype)
 def link(self, *args, **kwargs):
     kwargs.update(self.linker_opts)
     return link(args[0], validate_tuple(args[1], 2), *args[2:], **kwargs)
Example #17
0
def draw_feature(image, position, size, max_value=None, feat_func='gauss',
                 ecc=None, mask_diameter=None, **kwargs):
    """ Draws a radial symmetric feature and adds it to the image at given
    position. The given function will be evaluated at each pixel coordinate,
    no averaging or convolution is done.

    Parameters
    ----------
    image : ndarray
        image to draw features on
    position : iterable
        coordinates of feature position
    size : number
        the size of the feature (meaning depends on feature, for feat_gauss,
        it is the radius of gyration)
    max_value : number
        maximum feature value. should be much less than the max value of the
        image dtype, to avoid pixel wrapping at overlapping features
    feat_func : {'gauss', 'disc', 'ring'} or callable
        Default: 'gauss'
        When callable is given, it should take an ndarray of radius values
        and it should return intensity values <= 1
    ecc : positive number, optional
        eccentricity of feature, defined only in 2D. Identical to setting
        diameter to (diameter / (1 - ecc), diameter * (1 - ecc))
    mask_diameter :
        defines the box that will be drawn on. Default 8 * size.
    kwargs : keyword arguments are passed to feat_func
    """
    if len(position) != image.ndim:
        raise ValueError("Number of position coordinates should match image"
                         " dimensionality.")
    if not hasattr(feat_func, '__call__'):
        feat_func = feat_dict[feat_func]
    size = validate_tuple(size, image.ndim)
    if ecc is not None:
        if len(size) != 2:
            raise ValueError("Eccentricity is only defined in 2 dimensions")
        if size[0] != size[1]:
            raise ValueError("Diameter is already anisotropic; eccentricity is"
                             " not defined.")
        size = (size[0] / (1 - ecc), size[1] * (1 - ecc))
    if mask_diameter is None:
        mask_diameter = tuple([s * 8 for s in size])
    else:
        mask_diameter = validate_tuple(mask_diameter, image.ndim)
    if max_value is None:
        max_value = np.iinfo(image.dtype).max - 3
    rect = []
    vectors = []
    for (c, s, m, lim) in zip(position, size, mask_diameter, image.shape):
        if (c >= lim) or (c < 0):
            raise ValueError("Position outside of image.")
        lower_bound = max(int(np.floor(c - m / 2)), 0)
        upper_bound = min(int(np.ceil(c + m / 2 + 1)), lim)
        rect.append(slice(lower_bound, upper_bound))
        vectors.append(np.arange(lower_bound - c, upper_bound - c) / s)
    coords = np.meshgrid(*vectors, indexing='ij', sparse=True)
    r = np.sqrt(np.sum(np.array(coords)**2, axis=0))
    spot = max_value * feat_func(r, ndim=image.ndim, **kwargs)
    image[rect] += spot.astype(image.dtype)
Example #18
0
 def link(self, *args, **kwargs):
     kwargs.update(self.linker_opts)
     return link(args[0], validate_tuple(args[1], 2), *args[2:], **kwargs)