Skip to content

viewers.ClustersViewer

ClustersViewer

This class is used to visualize the clusters of a mesh using polyscope.

Parameters:

Name Type Description Default
V float numpy array

n x 3 vertex positions

required
T int numpy array

m x 4 tetrahedra indices

required
l int numpy array

T x 1 per-tet cluster indices.

required
eye_pos float numpy array

3 x 1 position of the camera

[2, 2, 2]
eye_target float numpy array

3 x 1 position of the camera target

[0, 0, 0]
path str

path to save the images to

''
R float numpy array

3 x 3 rotation matrix to apply to the mesh

identity(3)
period float

time between frames

1 / 60
vminmax float numpy array

2 x 1 min and max values for the color map

None
alpha float

transparency of the mesh

1
grouped bool

whether to group the clusters or not

True

Examples:

>>> import fast_cody as fcd
>>> [V, F, T] = fcd.read_msh(fcd.get_data("cd_fish.msh"))
>>> [B, l, Ws] = fcd.skinning_subspace(V, T, 10, 100)
>>> fcd.viewers.ClustersViewer(V, T, l)
Source code in src\fast_cody\viewers\ClustersViewer.py
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
class ClustersViewer():
    """
    This class is used to visualize the clusters of a mesh using polyscope.

    Parameters
    ----------
    V : float numpy array
        n x 3 vertex positions
    T : int numpy array
        m x 4 tetrahedra indices
    l : int numpy array
        T x 1  per-tet cluster indices.
    eye_pos : float numpy array
        3 x 1 position of the camera
    eye_target : float numpy array
        3 x 1 position of the camera target
    path : str
        path to save the images to
    R : float numpy array
        3 x 3 rotation matrix to apply to the mesh
    period : float
        time between frames
    vminmax : float numpy array
        2 x 1 min and max values for the color map
    alpha : float
        transparency of the mesh
    grouped : bool
        whether to group the clusters or not

    Examples
    --------
    >>> import fast_cody as fcd
    >>> [V, F, T] = fcd.read_msh(fcd.get_data("cd_fish.msh"))
    >>> [B, l, Ws] = fcd.skinning_subspace(V, T, 10, 100)
    >>> fcd.viewers.ClustersViewer(V, T, l)
    """
    def __init__(self, V, T, l,
              eye_pos = [2, 2, 2],
              eye_target = [0,0, 0],
              path="",
              R=np.identity(3), period=1/60,
                 vminmax=None, alpha=1, grouped=True):
        write_png = False
        if (path != ""):
            write_png = True
            os.makedirs(path, exist_ok=True)

        nc = np.max(l)+1
        ps.init()
        ps.look_at(eye_pos, eye_target)

        self.grouped = grouped
        self.V = V
        self.T = T
        self.path = path
        self.R = R
        self.l = l
        self.create_mesh(V@ R.T, T, l)
        self.i = 0
        self.write_png = write_png
        self.period = period
        self.vminmax = vminmax
        self.max_frame = nc
        self.id = 0
        self.nc = nc
        arr = np.arange(0, nc)
        np.random.shuffle(arr)
        self.arr = arr
        ps.set_user_callback(self.anim)
        ps.show()
        self.mesh.remove()


    def anim(self):
        if not (self.grouped):
            if (self.i < self.max_frame):
                mesh = self.mesh
                i = self.i
                ind = self.l == self.arr[i]
                self.create_mesh(self.V @ self.R.T, self.T[ind, :], self.l[ind])
                # ps.set_camera_rotation(self.R)
                if (self.write_png):
                    ps.screenshot(self.path + "/" + str(i).zfill(4) + ".png", False)
                self.i += 1
                time.sleep(self.period)
            else:
                changed, ID = psim.SliderInt("cluster label", self.id, v_min=0, v_max=self.nc)
                if changed:
                    self.id = ID
                    ind = self.l == ID
                    self.create_mesh(self.V @ self.R.T, self.T[ind, :], self.l[ind])
        else:
            if (self.i < self.max_frame):
                mesh = self.mesh
                i = self.i
                ind= np.zeros(self.T.shape[0], dtype=bool)
                for j in range(0, i+1):
                    ind = np.logical_or(ind,  (self.l == self.arr[j]))

                self.create_mesh(self.V @ self.R.T,  self.T[ind, :], self.l[ind])

                # ps.set_camera_rotation(self.R)
                if (self.write_png):
                    ps.screenshot(self.path + "/" + str(i).zfill(4) + ".png", False)
                self.i += 1
                time.sleep(self.period)
            else:
                self.create_mesh(self.V @ self.R.T, self.T, self.l)

        return



    def create_mesh(self, X, T, l):
        nc = np.max(l)

        if T.shape[1] == 4:
            self.mesh = ps.register_volume_mesh("mesh", X , T)
            self.mesh.add_scalar_quantity("clusters", l, defined_on='cells', cmap='rainbow', enabled=True, vminmax=[0, nc])
        elif T.shape[1] == 2:
            self.mesh = ps.register_curve_network("mesh", X, T)
            self.mesh.add_scalar_quantity("clusters", l, defined_on='edges', cmap='rainbow', enabled=True,
                                          vminmax=[0, nc])