pygmt
pygmt copied to clipboard
POC: Code PyGMT logo in PyGMT
Description of proposed changes
Related to https://github.com/GenericMappingTools/pygmt/issues/1404#issuecomment-2718559910, create the PyGMT logo in Python with PyGMT.
- Python script
- Separat method
Figure.pygmtlogoorFigure.logo_pygmtas part of theFigureclass or addition to the methodFigure.logo(which plots the GMT logo) - Gallery example
Preview:
- Documentation: https://pygmt-dev--3849.org.readthedocs.build/en/3849/api/generated/pygmt.Figure.pygmtlogo.html
- Gallery example: https://pygmt-dev--3849.org.readthedocs.build/en/3849/gallery/embellishments/pygmt_logo.html
- Script by @seisman to generate all versions See https://github.com/GenericMappingTools/pygmt/pull/3849#issuecomment-2753372170; modified version to use the changed parameter names at https://github.com/GenericMappingTools/pygmt/pull/3849#issuecomment-2754121028
- All combinations: https://pygmt-dev--3849.org.readthedocs.build/en/3849/_images/sphx_glr_pygmt_logo_004.png
Related to
- #1404
- #3848
- #3845
TODO:
- [x] Update intro comment of this PR
- [x] Remove temporary files (eps)
- [x] Include adding a wordmark and it's orientation to the input at the beginning
- [x] Update codes to finale version of the visual
- [x] space between horizontal line of letter G and letter M (https://github.com/GenericMappingTools/pygmt/pull/3849#discussion_r1994356616)
- [x] ending of yellow line at the right side of letter M (https://github.com/GenericMappingTools/pygmt/pull/3849#discussion_r1994388088)
- [x] clean boundary of shape (https://github.com/GenericMappingTools/pygmt/pull/3849/commits/0aea0b0dd0290af2d334b3cb3cfae7d664d7881b)
- [ ] etc.
- [x] Introduce variables
- [x] Improve parameter names, e.g.,
shape="circle" | "hexagon"orhex=False | True - [x] Convert to function (remove show and rdeuce save to tempoary eps files, replot via
Figure.image) - [x] Remove saving as eps file for rotation (first get ride of transparent margin)
- [x] Remove saving as eps file for adding wordmark (different basemaps due to horizontal and vertical orientation)
- [x] Convert to a method of the
Figureclass or addition toFigure.logo. - [ ] Add or expand gallery example to use the method
- [ ] Explain the story behind the logo in the gallery example
Issues:
- [x] Get ride of white or transparent margin
- [x] Currently the rotation and adding the wordmark are done in new
Figureobjects using the saved eps files. Maybe this is not easy to handle when converting to a method of theFigureclasse. - [ ] Decide about font for the wordmark (font Space Grotesk by Florian Karsten not available in GMT)
- [ ] No direct export to SVG format possible
- [ ] etc.
Reminders
- [ ] Run
make formatandmake checkto make sure the code follows the style guide. - [ ] Add tests for new features or tests that would have caught the bug that you're fixing.
- [ ] Add new public functions/methods/classes to
doc/api/index.rst. - [ ] Write detailed docstrings for all functions/methods.
- [ ] If wrapping a new module, open a 'Wrap new GMT module' issue and submit reasonably-sized PRs.
- [ ] If adding new functionality, add an example to docstrings or tutorials.
Slash Commands
You can write slash commands (/command) in the first line of a comment to perform
specific operations. Supported slash command is:
/format: automatically format and lint the code
/format
I feel the logo definition should be separated into a standalone method, similar to the method to plot the GMT logo. This would allow to plot the PyGMT logo by calling something like pygmt.Figure.pygmt_logo. The individual formats could be selected by different input parameters like you did or hex = True or darkmode = True.
ruff v0.10.0 was released 2 hours ago causing the newly falling code style checks.
- separat method
Figure.pygmtlogoorFigure.logo_pygmtas part of theFigureclass or addition to the methodFigure.logo(which plots the GMT logo)
@yvonnefroehlich You can follow the steps below:
- Create a
pygmtlogo.pyfile under thepygmt/src/directory - Move the current
pygmtlogofunction to this file - Add
selfas the first parameter of thepygmtlogofunction - Change
fig.image(line 269) toself.image. - Add
from pygmt.src.pygmtlogo import pygmtlogoinpygmt/src/__init__.py - Near line 429 in
pygmt/figure.py, addpygmtlogo.
Then, you should be able to call Figure.pygmtlogo to add the logo.
Click to view the script
from itertools import product
import pygmt
fig = pygmt.Figure()
# Logo without workmark.
fig.basemap(region=[0, 7, 0, 13], projection="x1c", frame="a1f1g1")
for x, y, darkmode in [(1, 3, False), (4, 3, True)]:
for blackwhite, hexshape in product([False, True], repeat=2):
fig.pygmtlogo(blackwhite=blackwhite, darkmode=darkmode, hexshape=hexshape, wordmark=False, position=f"g{x}/{y}+jTL+w2c")
y += 3
fig.shift_origin(xshift=8)
# Logo with vertical wordmark.
fig.basemap(region=[0, 7, 0, 13], projection="x1c", frame="a1f1g1")
for x, y, darkmode in [(1, 3, False), (4, 3, True)]:
for blackwhite, hexshape in product([False, True], repeat=2):
fig.pygmtlogo(blackwhite=blackwhite, darkmode=darkmode, hexshape=hexshape, wordmark="vertical", position=f"g{x}/{y}+jTL+w2c")
y += 3
fig.shift_origin(xshift=8)
# Logo with horizontal wordmark.
fig.basemap(region=[0, 20, 0, 13], projection="x1c", frame="a1f1g1")
for x, y, darkmode in [(1, 3, False), (11, 3, True)]:
for blackwhite, hexshape in product([False, True], repeat=2):
fig.pygmtlogo(blackwhite=blackwhite, darkmode=darkmode, hexshape=hexshape, wordmark="horizontal", position=f"g{x}/{y}+jTL+w0/2c")
y += 3
fig.show(width=1000)
fig.savefig("PyGMT-logo.pdf")
I've written a script to plot all 24 variants of the PyGMT logo so that we can visualize the logo design easily. The base maps are linear projections (projection="x1c") with a scale of 1:1. The logos have a width (or height) of 2 cm.
I've written a script to plot all 24 variants of the PyGMT logo so that we can visualize the logo design easily. The base maps are linear projections (projection="x1c") with a scale of 1:1. The logos have a width (or height) of 2 cm.
Great. Thanks 🙂! Much nicer code then my looping over all parameters 🙈.
Updated version to use the changed parameter names:
Click to view the script
# %%
# All versions
# modified from
# https://github.com/GenericMappingTools/pygmt/pull/3849#issuecomment-2753372170
# by @seisman
import pygmt
fig = pygmt.Figure()
# Logo without workmark.
fig.basemap(region=[0, 7, 0, 13], projection="x1c", frame="a1f1g1")
for x, y, theme in [(1, 3, "light"), (4, 3, "dark")]:
for color, shape in [
(True, "circle"),
(True, "hexagon"),
(False, "circle"),
(False, "hexagon"),
]:
fig.pygmtlogo(
color=color,
theme=theme,
shape=shape,
wordmark=False,
position=f"g{x}/{y}+jTL+w2c",
)
y += 3 # noqa: PLW2901
fig.shift_origin(xshift=8)
# Logo with vertical wordmark.
fig.basemap(region=[0, 7, 0, 13], projection="x1c", frame="a1f1g1")
for x, y, theme in [(1, 3, "light"), (4, 3, "dark")]:
for color, shape in [
(True, "circle"),
(True, "hexagon"),
(False, "circle"),
(False, "hexagon"),
]:
fig.pygmtlogo(
color=color,
theme=theme,
shape=shape,
wordmark="vertical",
position=f"g{x}/{y}+jTL+w2c",
)
y += 3 # noqa: PLW2901
fig.shift_origin(xshift=8)
# Logo with horizontal wordmark.
fig.basemap(region=[0, 20, 0, 13], projection="x1c", frame="a1f1g1")
for x, y, theme in [(1, 3, "light"), (11, 3, "dark")]:
for color, shape in [
(True, "circle"),
(True, "hexagon"),
(False, "circle"),
(False, "hexagon"),
]:
fig.pygmtlogo(
color=color,
theme=theme,
shape=shape,
wordmark="horizontal",
position=f"g{x}/{y}+jTL+w0/2c",
)
y += 3 # noqa: PLW2901
fig.show(width=1000)
I've created an animation showing how the logo is plotted step by step (perspective angle is set to 0 in this case):
https://github.com/user-attachments/assets/dd1d2bf4-d48e-4013-9ef5-69ad86ba9996
I also draw some circles with radius of r0, r1, r2, r3, r4, respectively, which I find useful when designing and debugging the logo:
I think we need to define one more radius for the outer radius of the curved horizontal line of letter T. The radius should be r2 + (r3-r4). In other words, we need to do the following:
- rename
r4tor5 - rename
r3tor4 - rename
r2tor3 - define the new
r2=0.58125, and replacer3 + (r4-r5)at lines 193-194 withr2.
I am thinking about the end of the compass line at the upper right edge of letter M:
| version 1 | version 2 (current version) | version 3 |
|---|---|---|
So far, we use version 2. I feel version 3 is too detailed. I have a preference for version 1. What do the others think?
So far, we use version 2. I feel version 3 is too detailed. I have a preference for version 1. What do the others think?
I also like version 1, then we can remove lines 149-152.
-
Updated animation for producing the logo step by step. It looks pretty good:
-
The "hexagon"-shape logo is not ideal, especially how the yellow compass lines intersect with the blue hexagon outline. I'm thinking if we should drop the hexagon logo in the initial version and add it later if there is still interest.
- What about renaming variables like
color_bluetoblue, to make the codes shorter?
I made two small updates (i) slightly smaller arrow head for letter T and (ii) shorten the vertical compass line:
| old | new |
|---|---|
So far I removed color from the variable names color_blue, color_yellow, and color_red.
I agree, the for the hexagon shape, the compass lines are not optimal.
I adjusted the position of the wordmark:
| circle | hexagon (for completness included) |
|---|---|
In case we keep or when we later add the hexagon version, we should make the circle and hexagon versions have the same overall size.
Just tried to adjust the codes to make the hexagon version look at bit better.
Now, the compass lines match the hexagon better, but letter T is a bit short.
@yvonnefroehlich Just in case it’s helpful, I’ve pushed the layered-animation branch, which contains a single commit fd97aea. This commit adds a simple feature: it saves the current figure as frame-xxx.png each time a plotting method is called.
When you run the Figure.pygmtlogo method, you’ll get multiple frame-xxx.png files, which you can then convert into an animation using a command like:
magick -delay 50 -loop 0 frame-*.png animation.gif