summaryrefslogtreecommitdiff
path: root/src/python/gudhi/tensorflow/cubical_layer.py
diff options
context:
space:
mode:
authorMathieuCarriere <mathieu.carriere3@gmail.com>2021-10-19 16:09:08 +0200
committerMathieuCarriere <mathieu.carriere3@gmail.com>2021-10-19 16:09:08 +0200
commit10be82856aee6eb7f4e704757b70c9dab6fe28b8 (patch)
tree5c2827f4277f46c45f8b0094303ca0b2ac217b13 /src/python/gudhi/tensorflow/cubical_layer.py
parent423c4be21968fd42c5470a9132d0e332c73ec2b9 (diff)
cleanup
Diffstat (limited to 'src/python/gudhi/tensorflow/cubical_layer.py')
-rw-r--r--src/python/gudhi/tensorflow/cubical_layer.py66
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