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

Figure.plot: Add the "symbol" parameter to support plotting data points with varying symbols #1117

Merged
merged 19 commits into from
Oct 29, 2024

Conversation

core-man
Copy link
Member

@core-man core-man commented Mar 24, 2021

Description of proposed changes

We can only plot different symbols via the data parameter in the plot method. This PR allows passing an array as symbols via the new symbol parameter. Meanwhile, we have to set style="0.2c", or set 1d-array sizes using style=True and sizes=sizes. Therefore, we now have four ways to set symbols and sizes, e.g.,

  • constant symbol and size: style="c0.5c"
  • constant symbol and different sizes: style="cc" + sizes=sizes
  • different symbols and constant size: style="0.5c" + symbol=symbol
  • different symbols and sizes: style=True + sizes=sizes + symbol=symbol

Two tests are added:

  • test_plot_fail_1d_array_using_data: Raise GMTInvalidInput if symbol is used with data parameter. Actually, I rename test_plot_fail_color_size_intensity to be this test function since we should raise such an error for 1d-array color, size, intensity and symbol parameters if they are used with the data parameter. (originally posted in The transparency parameter of plot/plot3d methods can be 1d array #1098 (comment))
  • test_plot_symbols: test 1d-array symbol (all are "c") with style="0.5c".

Related #1076

Reminders

  • Run make format and make check to 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 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 commands are:

  • /format: automatically format and lint the code
  • /test-gmt-dev: run full tests on the latest GMT development version

@core-man core-man marked this pull request as draft March 24, 2021 10:06
@core-man
Copy link
Member Author

core-man commented Apr 13, 2021

1c48b39: If the symbol parameter is used, we will automatically set style to be True if it is not set by the user.

Therefore, now we can plot different symbols and sizes like this: symbol=symbol, sizes=sizes. Note that the sizes parameter only accepts int and float (e.g., 1, 0.5) and does not accept string (e.g., 0.5c), so the unit can have to be set by the PROJ_LENGTH_UNIT using the config method if we don't want to use the default cm. (Also posted in #1076 (comment))

@@ -206,15 +210,18 @@ def plot(self, x=None, y=None, data=None, sizes=None, direction=None, **kwargs):
kind = data_kind(data, x, y)

extra_arrays = []
if "S" in kwargs and kwargs["S"][0] in "vV" and direction is not None:
extra_arrays.extend(direction)
if "S" in kwargs and isinstance(kwargs["S"], str):
Copy link
Member Author

Choose a reason for hiding this comment

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

I added isinstance(kwargs["S"], str) in case that the style parameter is True, False, None, int, or float.

@core-man core-man marked this pull request as ready for review April 13, 2021 08:07
@core-man core-man mentioned this pull request Apr 13, 2021
5 tasks
@seisman
Copy link
Member

seisman commented Apr 14, 2021

@core-man I think the co-existence of style and symbol parameters will lead to more confusion. We should discuss what we would like to use about the plot() and plot3d() functions.

@core-man
Copy link
Member Author

core-man commented Apr 14, 2021

@core-man I think the co-existence of style and symbol parameters will lead to more confusion. We should discuss what we would like to use about the plot() and plot3d() functions.

Actually, I'd like to fully avoid using the style parameter, and use a more Pythonic way, e.g., sizes, symbol, direction. But now I don't know if how much work will have to be done before the style parameter is avoided since plot/plot3d still have many unimplemented and complicated features/options.

We could remove the style parameter now and directly use symbol instead (see your suggestion in #1072 (comment)? What do you think? This is also related to Backwards compatibility and deprecation policy (#1120).

@core-man core-man mentioned this pull request Apr 15, 2021
5 tasks
@seisman
Copy link
Member

seisman commented May 7, 2021

I believe we need more discussions about what we would like to see about the plot() function.
I'll convert this PR to draft.

@seisman seisman marked this pull request as draft May 7, 2021 04:52
projection="X4c",
color="blue",
sizes=np.full(len(data[:, 0]), 0.5),
symbol=np.full(len(data[:, 0]), "c"),
Copy link
Member

Choose a reason for hiding this comment

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

At the moment, this test is checking that plotting all symbols as circles (c) work. A better test would be to test a mix of symbols such as circles (c), triangles (t), squares (s), etc (like your example in #1076 (comment)).

@weiji14 weiji14 added the enhancement Improving an existing feature label May 18, 2021
@maxrjones maxrjones added this to the 0.5.0 milestone Jun 15, 2021
@weiji14 weiji14 removed this from the 0.10.0 milestone Aug 24, 2023
@seisman seisman added this to the 0.12.0 milestone Dec 11, 2023
@seisman seisman removed this from the 0.12.0 milestone Feb 26, 2024
@seisman seisman marked this pull request as ready for review October 23, 2024 16:40
@seisman seisman changed the title Allow passing an array as symbols for plot Figure.plot: Add the "symbol" parameter to support plotting data points with varying symbols Oct 23, 2024
@seisman seisman added this to the 0.14.0 milestone Oct 23, 2024
@seisman seisman added the needs review This PR has higher priority and needs review. label Oct 23, 2024
@seisman
Copy link
Member

seisman commented Oct 24, 2024

The CI failures are caused by the codecov step. It's likely that codecov can't get the OIDC token for forks.

Edit: Likely related to upstream issue at codecov/codecov-action#1594.

@seisman seisman requested a review from a team October 27, 2024 04:36
@@ -87,6 +89,8 @@ def plot(self, data=None, x=None, y=None, size=None, direction=None, **kwargs):
size : 1-D array
The size of the data points in units specified using ``style``.
Only valid if using ``x``/``y``.
symbol : 1-D array
Copy link
Member

@weiji14 weiji14 Oct 28, 2024

Choose a reason for hiding this comment

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

Symbol can also be a single string right? E.g. symbol="t" for triangle. I think we need to add another unit test for the "constant-symbol and different sizes" case as mentioned at #1117 (comment)

Suggested change
symbol : 1-D array
symbol : str or 1-D array

Copy link
Member

Choose a reason for hiding this comment

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

No, similar to the size parameter, symbol must be a 1-D array.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm ok, I just tried with symbol="t" and it plotted a straight line:

import pygmt
fig = pygmt.Figure()
fig.plot(
    x=[1, 2, 3, 4],
    y=[1, 1, 1, 1],
    region=[0, 5, 0, 2],
    projection="X2c",
    fill="blue",
    size=[0.1, 0.2, 0.3, 0.4],
    symbol="t",
    frame="af",
)
fig.show()

plot_symbol

So yes, it does have to be a 1-D array.

Copy link
Member

Choose a reason for hiding this comment

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

Hm. Maybe writing "list of str" is clearer here?

Copy link
Member

Choose a reason for hiding this comment

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

1-D array is used here to match the types of other parameters. We probably can change it to Sequence[str] when we add typing hints.

Copy link
Member

@weiji14 weiji14 left a comment

Choose a reason for hiding this comment

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

Cheers @seisman for getting this over the line, I've tested this locally and it looks good. The changes look simple but there were a lot of refactorings in the PyGMT codebase to get this to work! Also thanks again @core-man for starting this effort 3 years ago, we'll finally be able to release this in PyGMT v0.14.0 🎉

P.S. We should also port these changes to plot3d later.

@seisman seisman merged commit b2dcd88 into GenericMappingTools:main Oct 29, 2024
10 of 18 checks passed
@seisman seisman removed the needs review This PR has higher priority and needs review. label Oct 29, 2024
@@ -87,6 +89,8 @@ def plot(self, data=None, x=None, y=None, size=None, direction=None, **kwargs):
size : 1-D array
The size of the data points in units specified using ``style``.
Copy link
Member

Choose a reason for hiding this comment

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

Hm. But if size is used with symbol the unit for size is given by the GMT / PyGMT defaults, correct?
Using style for specifing the unit in this case would be super confusing, e.g.:

...
size=[0.5, 0.8, 0.9],
symbol=["s", "c", "d"],
style="c",  # now centimeters, not circle
...

Copy link
Member

@seisman seisman Oct 29, 2024

Choose a reason for hiding this comment

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

Actually, it produces three circles with different sizes.

I want to emphasize that the "style" parameter was introduced in very early PyGMT versions. The docstrings are mostly copied from the upstream GMT documentation without further polishes, so they may make no sense for PyGMT.

projection="X4c",
fill="blue",
size=[0.1, 0.2, 0.3, 0.4],
symbol=["c", "t", "i", "s"],
Copy link
Member

Choose a reason for hiding this comment

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

Do size and symbol need to have to same length? Or is something like:

size=[0.1, 0.2, 0.3, 0.4],  # different sizes but same symbol
symbol=["c"],

or

size=[0.4],  # same size but different symbols
symbol=["c", "t", "i", "s"],

allowed?

Copy link
Member

Choose a reason for hiding this comment

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

Currently, they must be the same size.

Copy link
Member

Choose a reason for hiding this comment

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

Now I figured it out: One has to use the size or symbol parameter together with the style parameter 🙂.

Copy link
Member

@yvonnefroehlich yvonnefroehlich left a comment

Choose a reason for hiding this comment

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

I feel this introduction part in the docs for Figure.plot needs some adjustment to account for this newly added symbol parameter and to avoid confusions:

pygmt/pygmt/src/plot.py

Lines 65 to 70 in ce89ccb

If a symbol is selected and no symbol size given, then plot will
interpret the third column of the input data as symbol size. Symbols
whose size is <= 0 are skipped. If no symbols are specified then the
symbol code (see ``style`` below) must be present as last column in the
input. If ``style`` is not used, a line connecting the data points will
be drawn instead. To explicitly close polygons, use ``close``. Select a

Copy link
Member

@yvonnefroehlich yvonnefroehlich left a comment

Choose a reason for hiding this comment

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

This is definitely a nice enhancement!

So far, I only made some comments (will be back to work at the end of this week).

I feel there can be some confusions regarding the style, symbol, and size parameters. Maybe we should also extend or add a gallery example for this new parameter?

@seisman
Copy link
Member

seisman commented Oct 29, 2024

I feel this introduction part in the docs for Figure.plot needs some adjustment to account for this newly added symbol parameter and to avoid confusions:

pygmt/pygmt/src/plot.py

Lines 65 to 70 in ce89ccb

If a symbol is selected and no symbol size given, then plot will
interpret the third column of the input data as symbol size. Symbols
whose size is <= 0 are skipped. If no symbols are specified then the
symbol code (see ``style`` below) must be present as last column in the
input. If ``style`` is not used, a line connecting the data points will
be drawn instead. To explicitly close polygons, use ``close``. Select a

Currently, docstrings of most PyGMT methods/functions are copied literally from the upstream GMT documentation and may make no sense to PyGMT. I think we need to polish most docstrings carefully.

I feel there can be some confusions regarding the style, symbol, and size parameters. Maybe we should also extend or add a gallery example for this new parameter?

Yes, definitely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improving an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants