feat: add 3D interactive graph visualisation with Plotly#118
feat: add 3D interactive graph visualisation with Plotly#118yuvraajnarula wants to merge 9 commits intomllam:mainfrom
Conversation
|
Here's a simple script usage with icosahedral.py and plot_3D.py: flat_mesh = create_flat_icosahedral_mesh_graph(subdivisions=2)
nx.set_edge_attributes(flat_mesh, "m2m", name="component")
fig_flat = render_with_plotly(
flat_mesh,
show=True,
title="Flat Icosahedral Mesh (subdivisions=2)",
node_size=5.0,
edge_width=1.0,
component_colors={"m2m": "#43A047"},
)
hier_mesh = create_hierarchical_icosahedral_mesh_graph(max_subdivisions=3)
for u, v, attrs in hier_mesh.edges(data=True):
edge_level = attrs.get("level", "")
if isinstance(edge_level, str) and "_to_" in edge_level:
parts = edge_level.split("_to_")
comp = "mesh_up" if int(parts[0]) > int(parts[1]) else "mesh_down"
else:
comp = "m2m"
hier_mesh[u][v]["component"] = comp
custom_colors = {
**DEFAULT_COMPONENT_COLORS,
"m2m": "#1565C0"
"mesh_up": "#E53935",
"mesh_down": "#43A047",
}
fig_hier = render_with_plotly(
hier_mesh,
show=True,
title="Hierarchical Icosahedral Mesh (max_subdivisions=3)",
node_size=4.0,
edge_width=1.2,
component_colors=custom_colors,
)
fig_flat.write_html("flat_icosahedral.html")
fig_hier.write_html("hierarchical_icosahedral.html")
print("Saved flat_icosahedral.html and hierarchical_icosahedral.html") |
@leifdenby @joeloskarsson |
|
I think the flat representation for just the individual meshes are fine for the most part but I dont think its going overboard with the globe based visualization. At the least a spherical representation would be much better to understand the graph. Especially for the hierarchical flat graph its not that readable yeah? What I think is happening in the hierarchical one is that the coarser graphs are getting hidden beneath the finer graphs so theyre getting fully hidden, maybe trying to have those above would make it more readable? Overall for hierarchical having a concentric spherical representation is much better if not a proper globe one right now |
|
@Joltsy10 You were absolutely right: the flat layout (x=lon, y=lat, z=level) was hiding coarser mesh levels in hierarchical graphs. To fix that, I’ve added a concentric spherical layout as an option in plot_3d.py. Now you can call I also kept all the performance tricks you liked (edge batching, None separators, and optional plotly dependency). So, the concentric version stays just as browser-friendly. If you have a chance to test it on your graphs or have ideas for further improvements (e.g., textured Earth or different colour schemes), I’d love to hear them. Happy to collaborate on polishing it further. Thanks again for pushing this in the right direction. I really appreciate your input! This is the output I got while I am trying to work more on the 3d globe approach before pushing it. I hope @leifdenby considers this under the domain. |
|
usage : fig_hier_concentric = render_with_plotly(
hier_mesh,
show=True,
title="Hierarchical Icosahedral Mesh (concentric layout)",
node_size=4.0,
edge_width=1.2,
component_colors=custom_colors,
layout="concentric",
sphere_base_radius=1.0,
sphere_radius_step=0.5,
) |



Describe your changes
Adds
weather_model_graphs.visualise.plot_3dwith a single public entry point:Node positions are read from the existing
posnode attribute (x, y). The vertical axis (z) is derived from the integerlevelnode attribute present on mesh nodes in hierarchical and multiscale graphs. Grid nodes that carry noleveland are placed atz = -1so they always appear below all mesh levels, matching the convention agreed in #20.All edges of the same component (
g2m,m2m,m2g) are batched into a singleScatter3dtrace withNoneseparators between segments. This is the key performance fix discussed in #20: instead of one trace per edge (which produces >100 MB HTML files for global graphs), the entire component is one trace object, keeping output small and browser-friendly even for dense graphs.Node kinds (grid, mesh level 0, mesh level 1, …) are split into separate traces so the user gets independent legend toggles per level in the interactive figure.
plotlyis guarded as an optional dependency, and the rest ofweather_model_graphscan be imported without it. The function raises a clearImportErrorwith install instructions if plotly is absent, following the same pattern as the existingHAS_PYGguard insave.py.Two small edits are required in existing files:
src/weather_model_graphs/visualise/__init__.py— expose the new function:pyproject.toml— add plotly to an optional dependency group:Dependencies:
plotly(install withpip install weather-model-graphs[visualisation])numpy,networkx(already in core dependencies)Issue Link
Closes #20
Type of change
Checklist before requesting a review
pullwith--rebaseoption if possible).Checklist for reviewers
Each PR comes with its own improvements and flaws. The reviewer should check the following:
Author checklist after completed review
reflecting type of change (add section where missing):
Checklist for assignee