Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

graph layer #5861

Open
wants to merge 148 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 96 commits
Commits
Show all changes
148 commits
Select commit Hold shift + click to select a range
5ba80f3
starting graph layer implementation from points
JoOkuma May 12, 2023
e95b3d0
added _basepoints class
JoOkuma May 12, 2023
c45d2ec
1st replacement of self.data to self._points_data on _BasePoints
JoOkuma May 12, 2023
92d9dd9
init graph layer implementation
JoOkuma May 12, 2023
a3efea3
Merge branch 'main' into napari-graph-2023
JoOkuma May 16, 2023
891217b
graph slicing request / response and vispy visuals
JoOkuma May 16, 2023
37ddd96
add graph layer testing
JoOkuma May 19, 2023
89fb3cf
add add_graph example description
JoOkuma May 19, 2023
b5a0b94
refactored graph class to always operate on the cluster directly
JoOkuma May 22, 2023
d278b5a
add new delaunay graph example
JoOkuma May 22, 2023
9c8a390
update add_graph to follow other examples
JoOkuma May 22, 2023
fb0cb59
Merge branch 'main' into napari-graph-2023
JoOkuma May 22, 2023
66057a4
graph slicing bug fix
JoOkuma May 22, 2023
149c0d8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 22, 2023
dc4ff25
Merge branch 'main' into napari-graph-2023
JoOkuma May 22, 2023
6836979
Merge branch 'napari-graph-2023' of github.com:JoOkuma/napari into na…
JoOkuma May 22, 2023
a6564c7
fix change from precommit
JoOkuma May 22, 2023
cc8ff0f
Merge branch 'main' into napari-graph-2023
JoOkuma May 25, 2023
3c97c56
updated graphdata type
JoOkuma May 25, 2023
4a6a08c
replaced edges_ of points and graph layer with border_
JoOkuma May 25, 2023
7b12d4b
fixed basegraph typing when napari-graph is not installed
JoOkuma May 25, 2023
7ba748e
fixed mypy new type error
JoOkuma May 26, 2023
28ce0c8
Merge branch 'main' into napari-graph-2023
JoOkuma May 26, 2023
4cf0931
Update napari/layers/graph/graph.py
JoOkuma Jun 1, 2023
bbe6d46
minor fixes
JoOkuma Jun 1, 2023
3d5370c
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 1, 2023
c43ecd8
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 5, 2023
fef8077
removed predefined buffers size and fixed properties arguments
JoOkuma Jun 5, 2023
e1a0d32
fixing typing
JoOkuma Jun 5, 2023
9bbef0c
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 6, 2023
05b9aa2
add deprecation warning to edge -> border points arguments
JoOkuma Jun 6, 2023
eb8a90e
Update examples/add_graph.py
JoOkuma Jun 7, 2023
d07aa40
Update napari/layers/graph/graph.py
JoOkuma Jun 7, 2023
62519a5
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 8, 2023
f36c8bf
updated edge -> border deprecation version
JoOkuma Jun 8, 2023
05fe4b4
add deprecated points edge_ events warning
JoOkuma Jun 8, 2023
a910ca9
warning on warningemitter connecti
JoOkuma Jun 8, 2023
42bdb18
jni minor comments
JoOkuma Jun 13, 2023
90f80f9
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 13, 2023
f04520f
testing deprecated property with property func
JoOkuma Jun 13, 2023
81e9884
fixed bug by replacing instance method with class method
JoOkuma Jun 13, 2023
6e97eb5
fixed deprecation warning event test
JoOkuma Jun 13, 2023
3775280
improving nuclei segmentation graph example
JoOkuma Jun 13, 2023
d2036b0
replaced a few o private napari-graph class
JoOkuma Jun 13, 2023
981bd70
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 13, 2023
3c9c33d
update docs
JoOkuma Jun 13, 2023
f68f4b3
add networkx support
JoOkuma Jun 13, 2023
6b3ef25
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 16, 2023
6d8eb92
add since_version
JoOkuma Jun 16, 2023
bf509a8
using to_napari_graph API
JoOkuma Jun 16, 2023
2e16e74
using to_napari_graph API
JoOkuma Jun 16, 2023
c907ce0
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 20, 2023
98adf82
improving graph nodes removal
JoOkuma Jun 20, 2023
1f066bf
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 22, 2023
761c05e
fixed bug from merge with main
JoOkuma Jun 22, 2023
fd531c4
updating to new graph API
JoOkuma Jun 23, 2023
c747c74
Merge branch 'main' into napari-graph-2023
JoOkuma Jun 26, 2023
41eb555
fixing magicgui tests
JoOkuma Jun 27, 2023
b1a3482
fixed viewer and types tests
JoOkuma Jun 27, 2023
78cc0bc
fixing typing
JoOkuma Jun 27, 2023
3012731
Merge branch 'main' into napari-graph-2023
JoOkuma Jul 7, 2023
3f4cfd8
testing CI with numba>=0.57.0
JoOkuma Jul 7, 2023
9cd8395
added removed napari-graph install from python=3.11 and made napari-g…
JoOkuma Jul 7, 2023
0b289ee
downgranding numpy constraints
JoOkuma Jul 10, 2023
b7c1888
updated npe2 requirement
JoOkuma Jul 17, 2023
29063c9
Merge branch 'napari-graph-2023' of github.com:JoOkuma/napari into na…
JoOkuma Jul 17, 2023
c225c80
Merge branch 'main' into napari-graph-2023
JoOkuma Jul 17, 2023
ba3beca
removed napari graph not optional
JoOkuma Jul 18, 2023
6fa5c54
Apply suggestions from Juan's code review
JoOkuma Jul 18, 2023
6adaa7d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2023
08f6f3a
rolling back numpy constaints downgrade
JoOkuma Jul 18, 2023
ed52d96
Merge branch 'napari-graph-2023' of github.com:JoOkuma/napari into na…
JoOkuma Jul 18, 2023
f4ea067
fixing typing
JoOkuma Jul 19, 2023
1a7123f
fixed napari-graph numba warning
JoOkuma Jul 19, 2023
ad70173
Fixing 6016 errors
JoOkuma Jul 19, 2023
a580c0a
Merge branch 'main' into fix-6016
jni Jul 19, 2023
6b576a4
updated requirements
JoOkuma Jul 20, 2023
b2321ae
Merge branch 'fix-6016' of github.com:JoOkuma/napari into fix-6016
JoOkuma Jul 21, 2023
e363e96
Merge branch 'main' into napari-graph-2023
JoOkuma Jul 21, 2023
3731322
fix requirements
JoOkuma Jul 21, 2023
715ae5d
Merge branch 'main' into fix-6016
JoOkuma Jul 21, 2023
f23afd2
Merge branch 'fix-6016' into napari-graph-2023
JoOkuma Jul 21, 2023
0b39ce5
minor comments fix
JoOkuma Jul 21, 2023
cf1f40e
fixing czaki and jni comments
JoOkuma Jul 22, 2023
540636f
Merge branch 'main' into napari-graph-2023
JoOkuma Jul 22, 2023
b34884f
fixed tests
JoOkuma Jul 22, 2023
3b91999
Merge branch 'main' into napari-graph-2023
JoOkuma Jul 24, 2023
998d9f9
Final merge fixes
jni Aug 10, 2023
5cc814c
Only compute Delaunay graph in 2D
jni Aug 10, 2023
ff6ac5c
Add example of adding a networkx spatial graph directly
jni Aug 10, 2023
1f94fe9
Merge branch 'main' into napari-graph-2023
JoOkuma Aug 10, 2023
69ebbc4
fixing rolledback changes from 'border' -> 'edge' refactor
JoOkuma Aug 10, 2023
bef7d9e
Add networkx graph to graph layer test matrix
jni Aug 11, 2023
d608af6
Merge branch 'main' into napari-graph-2023
JoOkuma Aug 17, 2023
d466def
Merge branch 'main' into napari-graph-2023
JoOkuma Aug 22, 2023
ea2ac8c
converting networkx graph to napari-graph before testing
JoOkuma Aug 22, 2023
5315af3
Merge branch 'main' into napari-graph-2023
JoOkuma Oct 2, 2023
f969d6c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 2, 2023
6f9e718
fix add point bug
jamesyan-git Oct 13, 2023
b548030
add events to add/remove graph nodes
jamesyan-git Nov 6, 2023
b5c03fe
tidy up
jamesyan-git Nov 7, 2023
7f2e917
consistent use of vertex indices
jamesyan-git Nov 13, 2023
00dc63c
fix formatting
jamesyan-git Dec 13, 2023
2848ebb
change vertex indices from slected to -1
jamesyan-git Dec 13, 2023
7cb291d
Merge pull request #31 from jamesyan-git/fix_add
JoOkuma Dec 15, 2023
8ac802d
Merge main
DragaDoncila Dec 20, 2023
68ad317
pass through projection mode
DragaDoncila Dec 20, 2023
d055ceb
use indices instead of self.selected_data
jamesyan-git Dec 20, 2023
b30dc39
Something kinda working
DragaDoncila Dec 20, 2023
bbace5b
Remove spurious delete
DragaDoncila Dec 20, 2023
4f158af
Fix count of added nodes
jamesyan-git Jan 4, 2024
1901fd9
Merge branch 'napari-graph-2023' into fix-events
jamesyan-git Jan 4, 2024
bcabf32
more testing
jamesyan-git Jan 4, 2024
535ceca
More test
jamesyan-git Jan 4, 2024
458c338
fixt test
jamesyan-git Jan 5, 2024
ac460ee
Fixing tests after merge - tests passing
DragaDoncila Jan 5, 2024
4235019
add test for removing nodes
jamesyan-git Jan 5, 2024
6b80268
add remove_selected test
jamesyan-git Jan 5, 2024
b4ea210
clean up tests
jamesyan-git Jan 5, 2024
43a3bbd
Add selected_data setting
jamesyan-git Jan 5, 2024
9246384
address comments
jamesyan-git Jan 9, 2024
76cb651
Merge pull request #32 from jamesyan-git/fix-events
JoOkuma Jan 10, 2024
a367dba
Merge branch 'napari-graph-2023' of https://github.com/jookuma/napari…
DragaDoncila Jan 11, 2024
ef6e1a6
Actually working thick slices
DragaDoncila Jan 31, 2024
83755da
Merge main
DragaDoncila Feb 1, 2024
e03887a
Fix labels
DragaDoncila Feb 1, 2024
451b87b
Merge branch 'main' into napari-graph-2023
DragaDoncila Feb 1, 2024
efd0408
Merge main and fix some typing
DragaDoncila Feb 9, 2024
16b3a37
Fix tests and typing
DragaDoncila Feb 9, 2024
d8d8d21
More typing ignore
DragaDoncila Feb 9, 2024
e28e0c0
More typing fix
DragaDoncila Feb 9, 2024
9791e34
More typing fix
DragaDoncila Feb 9, 2024
758b2f5
Merge main...
Mar 26, 2024
b5b2472
More merging...?
Mar 26, 2024
34725fc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 26, 2024
e1998eb
Bring back napari graph dep
Mar 26, 2024
fec6bbb
Fix points layer
Mar 27, 2024
05395f6
Bring back og example
Mar 28, 2024
c2ded23
Merge branch 'napari-graph-2023' of https://github.com/JoOkuma/napari…
Mar 28, 2024
bc60ce3
Fixing conflicts
DragaDoncila Apr 19, 2024
6c21fc8
Fix points tests
DragaDoncila Apr 24, 2024
31b5703
Use node attribute to create node
ClementCaporal Apr 30, 2024
565934b
Rename _visual to node for GraphVisual
ClementCaporal Apr 30, 2024
6369a31
Update points.py to allow VispyPointsLayer.node access
ClementCaporal Apr 30, 2024
83ec8d5
Fix node point layer typing issue
ClementCaporal May 4, 2024
cebfffc
Fix graph node typing issue
ClementCaporal May 4, 2024
2f348fc
Merge pull request #40 from ClementCaporal/patch-1
JoOkuma May 4, 2024
5d5830a
fix typo
DragaDoncila May 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 23 additions & 0 deletions examples/add-graph-networkx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
Add networkx graph
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should rename to add_graph_networkx.py to group together with other graph examples

==================

Add a networkx graph directly to napari. This works as long as nodes
have a "pos" attribute with the node coordinate.

.. tags:: visualization-basic
"""

import networkx as nx

import napari

hex_grid = nx.hexagonal_lattice_graph(5, 5, with_positions=True)
# below conversion not needed after napari/napari-graph#11 is released
hex_grid_ints = nx.convert_node_labels_to_integers(hex_grid)

viewer = napari.Viewer()
layer = viewer.add_graph(hex_grid_ints, size=1)

if __name__ == "__main__":
napari.run()
38 changes: 38 additions & 0 deletions examples/add_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
Add graph
===================

Display a random undirected graph using the graph layer.

.. tags:: visualization-basic
"""

import numpy as np
import pandas as pd
from napari_graph import UndirectedGraph

import napari


def build_graph(n_nodes: int, n_neighbors: int) -> UndirectedGraph:
neighbors = np.random.randint(n_nodes, size=(n_nodes * n_neighbors))
edges = np.stack([np.repeat(np.arange(n_nodes), n_neighbors), neighbors], axis=1)

nodes_df = pd.DataFrame(
400 * np.random.uniform(size=(n_nodes, 4)),
columns=["t", "z", "y", "x"],
)
graph = UndirectedGraph(edges=edges, coords=nodes_df)

return graph


graph = build_graph(n_nodes=1_000_000, n_neighbors=5)

viewer = napari.Viewer()
layer = viewer.add_graph(graph, out_of_slice_display=True)


if __name__ == "__main__":

napari.run()
14 changes: 7 additions & 7 deletions examples/add_points_with_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@
face_color_cycle = ['blue', 'green']

# create a points layer where the face_color is set by the good_point feature
# and the edge_color is set via a color map (grayscale) on the confidence
# and the border_color is set via a color map (grayscale) on the confidence
# feature.
points_layer = viewer.add_points(
points,
features=features,
size=20,
edge_width=7,
edge_width_is_relative=False,
edge_color='confidence',
edge_colormap='gray',
border_width=7,
border_width_is_relative=False,
border_color='confidence',
border_colormap='gray',
face_color='good_point',
face_color_cycle=face_color_cycle
)

JoOkuma marked this conversation as resolved.
Show resolved Hide resolved
# set the edge_color mode to colormap
points_layer.edge_color_mode = 'colormap'
# set the border_color mode to colormap
points_layer.border_color_mode = 'colormap'


# bind a function to toggle the good_point annotation of the selected points
Expand Down
14 changes: 7 additions & 7 deletions examples/add_points_with_multicolor_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,23 @@
}

# create a points layer where the face_color is set by the good_point feature
# and the edge_color is set via a color map (grayscale) on the confidence
# and the border_color is set via a color map (grayscale) on the confidence
# feature
points_layer = viewer.add_points(
points,
features=features,
text=text,
size=20,
edge_width=7,
edge_width_is_relative=False,
edge_color='confidence',
edge_colormap='gray',
border_width=7,
border_width_is_relative=False,
border_color='confidence',
border_colormap='gray',
face_color='good_point',
face_color_cycle=color_cycle,
)

# set the edge_color mode to colormap
points_layer.edge_color_mode = 'colormap'
# set the border_color mode to colormap
points_layer.border_color_mode = 'colormap'

if __name__ == '__main__':
napari.run()
14 changes: 7 additions & 7 deletions examples/add_points_with_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,23 @@
}

# create a points layer where the face_color is set by the good_point feature
# and the edge_color is set via a color map (grayscale) on the confidence
# and the border_color is set via a color map (grayscale) on the confidence
# feature.
points_layer = viewer.add_points(
points,
features=features,
text=text,
size=20,
edge_width=7,
edge_width_is_relative=False,
edge_color='confidence',
edge_colormap='gray',
border_width=7,
border_width_is_relative=False,
border_color='confidence',
border_colormap='gray',
face_color='good_point',
face_color_cycle=face_color_cycle,
)

# set the edge_color mode to colormap
points_layer.edge_color_mode = 'colormap'
# set the border_color mode to colormap
points_layer.border_color_mode = 'colormap'

if __name__ == '__main__':
napari.run()
4 changes: 2 additions & 2 deletions examples/mgui_with_threadpoolexec_.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def _make_blob():
data = blobs[:, : image.ndim]
kwargs = {
"size": blobs[:, -1],
"edge_color": "red",
"edge_width": 2,
"border_color": "red",
"border_width": 2,
"face_color": "transparent",
}
return (data, kwargs, 'points')
Expand Down
4 changes: 2 additions & 2 deletions examples/mgui_with_threadworker_.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def detect_blobs() -> LayerDataTuple:
points = blobs[:, : image.ndim]
meta = {
"size": blobs[:, -1],
"edge_color": "red",
"edge_width": 2,
"border_color": "red",
"border_width": 2,
"face_color": "transparent",
}
# return a "LayerDataTuple"
Expand Down
14 changes: 7 additions & 7 deletions examples/nD_points_with_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,30 @@
[True, True, True, True, False, False, False, False]
* int(blobs.shape[0] / 2)
)
edge_feature = np.array(['A', 'B', 'C', 'D', 'E'] * int(len(points) / 5))
border_feature = np.array(['A', 'B', 'C', 'D', 'E'] * int(len(points) / 5))

features = {
'face_feature': face_feature,
'edge_feature': edge_feature,
'border_feature': border_feature,
}

points_layer = viewer.add_points(
points,
features=features,
size=3,
edge_width=5,
edge_width_is_relative=False,
edge_color='edge_feature',
border_width=5,
border_width_is_relative=False,
border_color='border_feature',
face_color='face_feature',
out_of_slice_display=False,
)

# change the face color cycle
points_layer.face_color_cycle = ['white', 'black']

# change the edge_color cycle.
# change the border_color cycle.
# there are 4 colors for 5 categories, so 'c' will be recycled
points_layer.edge_color_cycle = ['c', 'm', 'y', 'k']
points_layer.border_color_cycle = ['c', 'm', 'y', 'k']

if __name__ == '__main__':
napari.run()
44 changes: 44 additions & 0 deletions examples/nuclei_segmentation_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
Nuclei Segmentation Graph
===============

Creates a delaunay graph from maxima of cell nuclei.

.. tags:: visualization-nD
"""
from itertools import combinations

import numpy as np
from napari_graph import UndirectedGraph
from scipy.spatial import Delaunay
from skimage import data, feature, filters

import napari


def delaunay_edges(points: np.ndarray) -> np.ndarray:
delaunay = Delaunay(points)
edges = set()
for simplex in delaunay.simplices:
# each simplex is represented as a list of four points.
# we add all edges between the points to the edge list
edges |= set(combinations(simplex, 2))

return np.asarray(list(edges))


cells = data.cells3d()

nuclei = cells[:, 1]
smooth = filters.gaussian(nuclei, sigma=10)
nodes_coords = feature.peak_local_max(smooth)
edges = delaunay_edges(nodes_coords[:, 1:])
graph = UndirectedGraph(edges, nodes_coords)
viewer, image_layer = napari.imshow(
cells, channel_axis=1, name=['membranes', 'nuclei'], ndisplay=3
)
graph_layer = viewer.add_graph(graph)
viewer.camera.angles = (10, -20, 130)

if __name__ == '__main__':
napari.run()
2 changes: 1 addition & 1 deletion examples/spherical_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
face_color=colors,
size=sizes,
shading='spherical',
edge_width=0,
border_width=0,
)

# antialiasing is currently a bit broken, this is especially bad in 3D so
Expand Down
1 change: 1 addition & 0 deletions napari/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
'utils': ['sys_info'],
'utils.notifications': ['notification_manager'],
'view_layers': [
'view_graph',
'view_image',
'view_labels',
'view_path',
Expand Down
2 changes: 2 additions & 0 deletions napari/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import napari.utils.notifications
from napari._qt.qt_event_loop import gui_qt, run
from napari.plugins.io import save_layers
from napari.view_layers import (
view_graph,
view_image,
view_labels,
view_path,
Expand All @@ -20,6 +21,7 @@ notification_manager: napari.utils.notifications.NotificationManager
__all__ = (
'Viewer',
'current_viewer',
'view_graph',
'view_image',
'view_labels',
'view_path',
Expand Down
5 changes: 5 additions & 0 deletions napari/_qt/layer_controls/qt_graph_controls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from napari._qt.layer_controls.qt_points_controls import QtPointsControls


class QtGraphControls(QtPointsControls):
pass
JoOkuma marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions napari/_qt/layer_controls/qt_layer_controls_container.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from qtpy.QtWidgets import QFrame, QStackedWidget

from napari._qt.layer_controls.qt_graph_controls import QtGraphControls
from napari._qt.layer_controls.qt_image_controls import QtImageControls
from napari._qt.layer_controls.qt_labels_controls import QtLabelsControls
from napari._qt.layer_controls.qt_points_controls import QtPointsControls
Expand All @@ -8,6 +9,7 @@
from napari._qt.layer_controls.qt_tracks_controls import QtTracksControls
from napari._qt.layer_controls.qt_vectors_controls import QtVectorsControls
from napari.layers import (
Graph,
Image,
Labels,
Points,
Expand All @@ -20,6 +22,7 @@

layer_to_controls = {
Labels: QtLabelsControls,
Graph: QtGraphControls,
Image: QtImageControls,
Points: QtPointsControls,
Shapes: QtShapesControls,
Expand Down