DerThorsten / nifty

A nifty library for graph based image segmentation.
MIT License
41 stars 21 forks source link

nifty.graph.rag.gridRag constructor fails when invoked with 2D or 3D array with at least one singleton dimension #104

Closed hanslovsky closed 7 years ago

hanslovsky commented 7 years ago

I wanted to generate a dummy nifty.graph.rag.gridRag from a numpy array so I could use IPython auto complete to explore the gridRag API. The constructor failed as shown below when using 2D or 3D numpy.ndarray with at least one singleton dimension.

The failure mode for 2D and 3D with one and two singleton dimensions, respectively, can be traced back to the dimensionality check which is evaluated on np.squeeze( labels ): https://github.com/DerThorsten/nifty/blob/master/src/python/module/nifty/graph/rag/__init__.py#L23 https://github.com/DerThorsten/nifty/blob/master/src/python/module/nifty/graph/rag/__init__.py#L29

The failure mode for 3D with one singleton dimension could be rooted in the inconsistency of the dimensionality check (np.squeeze( labels ) ) and the call to explicitLabelsGridRag2D (labels without np.squeeze).

Mentioning @constantinpape so he is aware of this issue.

# prerequisites
>>> import nifty.graph.rag as nrag
>>> import numpy as np

# 2D with one singleton dimension
>>> print( nrag.gridRag( np.zeros( ( 3, 1 ), dtype=np.uint32 ) ) )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/hanslovskyp/local/lib/python3.6/site-packages/nifty/graph/rag/__init__.py", line 34, in gridRag
    raise RuntimeError("wrong dimension, currently only 2D and 3D is implemented")
RuntimeError: wrong dimension, currently only 2D and 3D is implemented

# 2D without singleton dimension
>>> print( nrag.gridRag( np.zeros( ( 3, 3 ), dtype=np.uint32 ) ) )
#Nodes 1 #Edges 0

# 3D with two singleton dimensions
>>> print( nrag.gridRag( np.zeros( ( 3, 1, 1 ), dtype=np.uint32 ) ) )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/hanslovskyp/local/lib/python3.6/site-packages/nifty/graph/rag/__init__.py", line 34, in gridRag
    raise RuntimeError("wrong dimension, currently only 2D and 3D is implemented")
RuntimeError: wrong dimension, currently only 2D and 3D is implemented

# 3D with one singleton dimensions
>>> print( nrag.gridRag( np.zeros( ( 3, 3, 1 ), dtype=np.uint32 ) ) )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/hanslovskyp/local/lib/python3.6/site-packages/nifty/graph/rag/__init__.py", line 24, in gridRag
    return explicitLabelsGridRag2D(labels, numberOfThreads=int(numberOfThreads))
TypeError: explicitLabelsGridRag2D(): incompatible function arguments. The following argument types are supported:
    1. (labels: array<int>, numberOfThreads: int=-1) -> nifty.graph.rag._rag.ExplicitLabelsGridRag2D
    2. (labels: array<int>, serialization: array<int>) -> nifty.graph.rag._rag.ExplicitLabelsGridRag2D

Invoked with: array([[[0],
        [0],
        [0]],

       [[0],
        [0],
        [0]],

       [[0],
        [0],
        [0]]], dtype=uint32); kwargs: numberOfThreads=-1

#3D without singleton dimensions
>>> print( nrag.gridRag( np.zeros( ( 3, 3, 3 ), dtype=np.uint32 ) ) )
#Nodes 1 #Edges 0
DerThorsten commented 7 years ago

ok, i guess squeezing is a bad idea here! I'll fix that soonish =). The behavior should be: If there is a singleton assume it is an intended singleton.

DerThorsten commented 7 years ago

@hanslovsky could you reopen the pr against the dev branch