Skip to content

added the download image button - #3

Closed
blueprintparadise wants to merge 1 commit into
punnerud:mainfrom
blueprintparadise:adding_download_button
Closed

added the download image button#3
blueprintparadise wants to merge 1 commit into
punnerud:mainfrom
blueprintparadise:adding_download_button

Conversation

@blueprintparadise

Copy link
Copy Markdown
Contributor

Added an option to download the graph as a png.

Added an option to download the graph as a png for future reference,
@blueprintparadise

Copy link
Copy Markdown
Contributor Author

Hey @punnerud , any update on this ?

@punnerud

punnerud commented Aug 10, 2026

Copy link
Copy Markdown
Owner

@blueprintparadise Thanks for this, and sorry for the wait. The feature is wanted and it is included in #4 — with the export moved to the client side, and you credited via Co-authored-by.

The reason for changing the implementation rather than merging as-is: the server-side version re-plots the graph with networkx.spring_layout, which lays the nodes out from scratch. So the button says "Download PNG" but hands back a different picture than the one on screen — different positions, no node sizing, no edge weights. Since vis.js already renders to a <canvas>, canvas.toBlob() gives exactly what the user is looking at, with no new dependency.

Three other things that would have bitten in production:

  • latest_graph_data is a module-level global, so two people querying at once overwrite each other's graph and can download someone else's result.
  • matplotlib.pyplot inside a Flask request thread needs matplotlib.use("Agg") first; without it the default backend can try to touch the GUI and crash, which on macOS is a hard failure.
  • e["value"] raises KeyError on any edge without that key.

Also, the imported FileSaver.js is never used, and dropping stream_with_context from the imports is fine only because it was already unused.

If you would rather have the server-side route as well — for scripting or automation, where there is no canvas to read — that is a reasonable thing to want and I would take a follow-up PR for a /export/image that takes the graph in the request body instead of reading a global, with the Agg backend set explicitly.

Superseded by #4, but the feature is yours — leaving this open for @punnerud to decide.

@punnerud

Copy link
Copy Markdown
Owner

@blueprintparadise Your feature is shipped and released — it is in mpe-lkg 0.3.0, and you are credited with Co-authored-by on the commit.

Closing this one because it can no longer be merged: the conflicts GitHub is showing are in exactly the three files that moved or went away when the project became a pip package — app.py is now src/mpe_lkg/app.py, templates/index.html is now src/mpe_lkg/templates/index.html, and requirements.txt was replaced by pyproject.toml. Resolving them would mean reinstating the server-side rendering that was deliberately swapped out, so there is nothing here left to merge.

For the record, the reason for the swap rather than a straight merge: networkx.spring_layout lays the nodes out from scratch, so the button said "Download PNG" but handed back a different picture than the one on screen — different positions, no node sizing, no edge weights. vis.js already renders to a <canvas>, so canvas.toBlob() gives exactly what the user is looking at, with no new dependency. The global latest_graph_data, matplotlib.pyplot in a Flask thread without the Agg backend, and the KeyError on e["value"] were the other three reasons.

If you still want a server-side route for scripting — where there is no canvas to read — that is a reasonable thing to want and I would take a fresh PR for a /export/image that takes the graph in the request body instead of reading a global, with Agg set explicitly. Thanks for the contribution, and sorry it sat for so long.

@punnerud punnerud closed this Aug 10, 2026
punnerud added a commit that referenced this pull request Aug 11, 2026
The same text as mpedb and MPEqs, byte for byte, so the three projects share
one licence rather than three that can drift apart.

Free of charge for every person and every organization, except that a group
over five billion dollars in revenue or valuation owes seven US cents per
device, once.

The OSI classifier is removed rather than swapped: this licence is not OSI
approved, and "License :: OSI Approved :: MIT License" would have been a false
claim in the package metadata. It now reads Other/Proprietary, and the LICENSE
file ships inside the wheel.

ONE THING WORTH KNOWING BEFORE THIS GOES OUT. This repository has had outside
contributions, and PR #3's author is credited with Co-authored-by on the
download-image commit. Their work was offered when the project said MIT.
In practice nothing of theirs remains in the tree -- that feature was
reimplemented on the client side, and the server-side version it replaced is
not in any current file -- so this is a relicensing of code that is ours. It
is still worth recording that the question was asked rather than skipped.

Version 0.4.0, because the licence a package is distributed under is not a
patch-level detail.
punnerud added a commit that referenced this pull request Aug 11, 2026
The same text as mpedb and MPEqs, byte for byte, so the three projects share
one licence rather than three that can drift apart.

Free of charge for every person and every organization, except that a group
over five billion dollars in revenue or valuation owes seven US cents per
device, once.

The OSI classifier is removed rather than swapped: this licence is not OSI
approved, and "License :: OSI Approved :: MIT License" would have been a false
claim in the package metadata. It now reads Other/Proprietary, and the LICENSE
file ships inside the wheel.

ONE THING WORTH KNOWING BEFORE THIS GOES OUT. This repository has had outside
contributions, and PR #3's author is credited with Co-authored-by on the
download-image commit. Their work was offered when the project said MIT.
In practice nothing of theirs remains in the tree -- that feature was
reimplemented on the client side, and the server-side version it replaced is
not in any current file -- so this is a relicensing of code that is ours. It
is still worth recording that the question was asked rather than skipped.

Version 0.4.0, because the licence a package is distributed under is not a
patch-level detail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants