diff options
author | MathieuCarriere <mathieu.carriere3@gmail.com> | 2021-10-19 16:09:08 +0200 |
---|---|---|
committer | MathieuCarriere <mathieu.carriere3@gmail.com> | 2021-10-19 16:09:08 +0200 |
commit | 10be82856aee6eb7f4e704757b70c9dab6fe28b8 (patch) | |
tree | 5c2827f4277f46c45f8b0094303ca0b2ac217b13 /src/python/gudhi/tensorflow/cubical_layer.py | |
parent | 423c4be21968fd42c5470a9132d0e332c73ec2b9 (diff) |
cleanup
Diffstat (limited to 'src/python/gudhi/tensorflow/cubical_layer.py')
-rw-r--r-- | src/python/gudhi/tensorflow/cubical_layer.py | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/python/gudhi/tensorflow/cubical_layer.py b/src/python/gudhi/tensorflow/cubical_layer.py new file mode 100644 index 00000000..e36adec5 --- /dev/null +++ b/src/python/gudhi/tensorflow/cubical_layer.py @@ -0,0 +1,66 @@ +import numpy as np +import tensorflow as tf +from ..cubical_complex import CubicalComplex + +###################### +# Cubical filtration # +###################### + +# The parameters of the model are the pixel values. + +def _Cubical(X, dimension): + # Parameters: X (image), + # dimension (homology dimension) + + # Compute the persistence pairs with Gudhi + cc = CubicalComplex(dimensions=X.shape, top_dimensional_cells=X.flatten()) + cc.persistence() + try: + cof = cc.cofaces_of_persistence_pairs()[0][dimension] + except IndexError: + cof = np.array([]) + + if len(cof) > 0: + # Sort points with distance-to-diagonal + Xs = X.shape + pers = [X[np.unravel_index(cof[idx,1], Xs)] - X[np.unravel_index(cof[idx,0], Xs)] for idx in range(len(cof))] + perm = np.argsort(pers) + cof = cof[perm[::-1]] + + # Retrieve and ouput image indices/pixels corresponding to positive and negative simplices + D = len(Xs) if len(cof) > 0 else 1 + ocof = np.array([0 for _ in range(D*2*cof.shape[0])]) + count = 0 + for idx in range(0,2*cof.shape[0],2): + ocof[D*idx:D*(idx+1)] = np.unravel_index(cof[count,0], Xs) + ocof[D*(idx+1):D*(idx+2)] = np.unravel_index(cof[count,1], Xs) + count += 1 + return np.array(ocof, dtype=np.int32) + +class CubicalLayer(tf.keras.layers.Layer): + """ + TensorFlow layer for computing cubical persistence out of a cubical complex + + Attributes: + dimension (int): homology dimension + """ + def __init__(self, dimension=1, **kwargs): + super().__init__(dynamic=True, **kwargs) + self.dimension = dimension + + def build(self): + super.build() + + def call(self, X): + """ + Compute persistence diagram associated to a cubical complex filtered by some pixel values + + Parameters: + X (TensorFlow variable): pixel values of the cubical complex + """ + # Compute pixels associated to positive and negative simplices + # Don't compute gradient for this operation + indices = tf.stop_gradient(_Cubical(X.numpy(), self.dimension)) + # Get persistence diagram by simply picking the corresponding entries in the image + dgm = tf.reshape(tf.gather_nd(X, tf.reshape(indices, [-1,len(X.shape)])), [-1,2]) + return dgm |