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

Add gallery example for Figure.ternary method #2138

Merged
merged 16 commits into from
Dec 27, 2022
Merged

Add gallery example for Figure.ternary method #2138

merged 16 commits into from
Dec 27, 2022

Conversation

michaelgrund
Copy link
Member

Description of proposed changes

This PR adds a gallery example showing the usage of Figure.ternary(). Example is adopted from the corresponding GMT docs.

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 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 commands are:

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

@michaelgrund michaelgrund added the documentation Improvements or additions to documentation label Sep 25, 2022
@michaelgrund michaelgrund added this to the 0.8.0 milestone Sep 25, 2022
@michaelgrund michaelgrund marked this pull request as draft September 25, 2022 12:57
@michaelgrund michaelgrund mentioned this pull request Oct 6, 2022
6 tasks
michaelgrund added a commit that referenced this pull request Nov 25, 2022
@michaelgrund michaelgrund mentioned this pull request Nov 25, 2022
6 tasks
Co-authored-by: Dongdong Tian <seisman.info@gmail.com>
Co-authored-by: Will Schlitzer <schlitzer90@gmail.com>
Co-authored-by: Yvonne Fröhlich <94163266+yvonnefroehlich@users.noreply.github.com>
@michaelgrund
Copy link
Member Author

Currently running the example does not work. The issue is related to the input data. Right now it's loaded as pd.DataFrame which leads to a dying kernel when using it e.g. in a jupyter notebook. However, when converting to a numpy array via data = data.to_numpy() the example works as expected. Any ideas what's the problem here @GenericMappingTools/pygmt-maintainers ?

@yvonnefroehlich
Copy link
Member

Currently running the example does not work. The issue is related to the input data. Right now it's loaded as pd.DataFrame which leads to a dying kernel when using it e.g. in a jupyter notebook. However, when converting to a numpy array via data = data.to_numpy() the example works as expected. Any ideas what's the problem here @GenericMappingTools/pygmt-maintainers ?

I set up different pandas DataFrames (please see code examples below). Surprisingly, the occurring issue seems at least partly related to the dtype of the values (float or integer):

  • All columns contain at least one float value, i.e. for each column is dtype: float64-> FAILS [see cases (I) and (III)]
  • One column contains only integer values, i.e. for this column is dtype: int64 -> WORKS [see case (II)]

Currently, I do not understand and can not explain why this happens. The issue occurs on both Windows and Linux using a dev version of PyGMT and GMT 6.4.0 (please see error message and system information below).

Code example

import pygmt
import pandas as pd

#-----------------------------------------------------------------------------
# (I) first rows of dataset "rock_compositions"
dict_self = {'a': [0.160, 0.220, 0.090, 0.660],
             'b': [0.331, 0.625, 0.180, 0.258],
             'c': [0.509, 0.158, 0.732, 0.078],
             'd': [9.344, 39.156, 2.621, 12.062]}
df_self = pd.DataFrame(data=dict_self)
sum_rows = df_self.a + df_self.b + df_self.c
print(sum_rows)  # not exactly 1, i.e., 100 %, for all rows
print(df_self.d)
# -> FAILS

# (II) e.g., column "d" with integer values
dict_self = {'a': [0.160, 0.220, 0.090, 0.660],
             'b': [0.331, 0.625, 0.180, 0.258],
             'c': [0.509, 0.158, 0.732, 0.078],
             'd': [9, 39, 2, 12]}
df_self = pd.DataFrame(data=dict_self)
print(df_self.d)
# -> WORKS

# (III) e.g., change first value in column "d" to float
dict_self = {'a': [0.160, 0.220, 0.090, 0.660],
             'b': [0.331, 0.625, 0.180, 0.258],
             'c': [0.509, 0.158, 0.732, 0.078],
             'd': [9.0, 39, 2, 12]}
df_self = pd.DataFrame(data=dict_self)
print(df_self.d)
# -> FAILS

#%%
#-----------------------------------------------------------------------------
# create Cartesian scatter plot
# for controll - WORKS for all pandas DataFrames
fig = pygmt.Figure()

# set up colormap
pygmt.makecpt(cmap="batlow", series=[0, 80, 1])

fig.plot(
    df_self,
    region=[0, 1, 0, 1],
    projection="X10c",
    style="c",
    cmap=True,
    pen="1p,black",
    frame=["afg", "+givory"],
    incols=[0, 1, 3, 2],
)
fig.show()

#-----------------------------------------------------------------------------
# create ternary diagram
# a, b, c axes be positive in a counter-clockwise direction
fig = pygmt.Figure()

# set up colormap
pygmt.makecpt(cmap="batlow", series=[0, 80, 10])

fig.ternary(
    df_self,
    region=[0, 100, 0, 100, 0, 100],  # input values are all in [0,1], internally multipled with 100 to be in percent?
    width="10c",  # -JX
    style="c0.25c",
    cmap=True,
    pen="1p,black",
    frame=["aafg", "bafg", "cagf", "+givory"],
)
fig.show()

Error message
Windows

Windows fatal exception: code 0xc0000374


Main thread:
Current thread 0x0000130c (most recent call first):
  File "C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\lib\site-packages\pygmt\clib\session.py", line 506 in call_module
  File "C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\lib\site-packages\pygmt\src\ternary.py", line 84 in ternary
  File "C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\lib\site-packages\pygmt\helpers\decorators.py", line 734 in new_module
  File "C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\lib\site-packages\pygmt\helpers\decorators.py", line 594 in new_module
  File "c:\users\admin\c2\eigenedokumente\studium\promotion\e_gmt\00_testing\issue_terneray\ternary_github.py", line 63 in <module>
  File "C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\lib\site-packages\spyder_kernels\py3compat.py", line 356 in compat_exec
  File "C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 469 in exec_code
  File "C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 611 in _exec_file
  File "C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 524 in runfile
  File "C:\Users\Admin\AppData\Local\Temp\ipykernel_19428\2603873820.py", line 1 in <cell line: 1>


Restarting kernel...

Linux

Fatal Python error: Aborted


Thread 0x00007f9ef7f47700 (most recent call first):
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/zmq/utils/garbage.py", line 47 in run
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/threading.py", line 980 in _bootstrap_inner
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/threading.py", line 937 in _bootstrap



Main thread:
Current thread 0x00007f9fdb8d5740 (most recent call first):
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/pygmt/clib/session.py", line 506 in call_module
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/pygmt/src/ternary.py", line 84 in ternary
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/pygmt/helpers/decorators.py", line 734 in new_module
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/pygmt/helpers/decorators.py", line 594 in new_module
  File "/home/yfroe/Documents/E_GMT/00_testing/issue_ternary/ternary_github.py", line 81 in <module>
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/spyder_kernels/py3compat.py", line 356 in compat_exec
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/spyder_kernels/customize/spydercustomize.py", line 469 in exec_code
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/spyder_kernels/customize/spydercustomize.py", line 611 in _exec_file
  File "/home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/python3.9/site-packages/spyder_kernels/customize/spydercustomize.py", line 524 in runfile
  File "/tmp/ipykernel_7652/2412465561.py", line 1 in <cell line: 1>


Kernel wird neu gestartet...

System information
Windows

(pygmt_env_080_640_dev02) C:\Users\Admin>python -c "import pygmt; pygmt.show_versions()"
PyGMT information:
  version: v0.7.1.dev193
System information:
  python: 3.9.15 | packaged by conda-forge | (main, Nov 22 2022, 08:39:05) [MSC v.1929 64 bit (AMD64)]
  executable: C:\ProgramData\Anaconda3\envs\pygmt_env_080_640_dev02\python.exe
  machine: Windows-10-10.0.19045-SP0
Dependency information:
  numpy: 1.23.5
  pandas: 1.5.2
  xarray: 2022.12.0
  netCDF4: 1.6.2
  packaging: 21.3
  geopandas: None
  ghostscript: 9.54.0
GMT library information:
  binary version: 6.4.0
  cores: 4
  grid layout: rows
  library path: C:/ProgramData/Anaconda3/envs/pygmt_env_080_640_dev02/Library/bin/gmt.dll
  padding: 2
  plugin dir: C:/ProgramData/Anaconda3/envs/pygmt_env_080_640_dev02/Library/bin/gmt_plugins
  share dir: C:/Program Files (x86)/gmt6/share
  version: 6.4.0

Linux

(pygmt_env_080_640_dev02) yfroe@gpiseis16:~> python -c "import pygmt; pygmt.show_versions()"
PyGMT information:
  version: v0.7.1.dev194
System information:
  python: 3.9.15 | packaged by conda-forge | (main, Nov 22 2022, 15:55:03)  [GCC 10.4.0]
  executable: /home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/bin/python
  machine: Linux-5.14.21-150400.24.18-default-x86_64-with-glibc2.31
Dependency information:
  numpy: 1.23.5
  pandas: 1.5.2
  xarray: 2022.12.0
  netCDF4: 1.6.2
  packaging: 22.0
  geopandas: None
  ghostscript: 9.54.0
GMT library information:
  binary version: 6.4.0
  cores: 20
  grid layout: rows
  library path: /home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/libgmt.so
  padding: 2
  plugin dir: /home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/lib/gmt/plugins
  share dir: /home/yfroe/anaconda3/envs/pygmt_env_080_640_dev02/share/gmt
  version: 6.4.0

@yvonnefroehlich yvonnefroehlich mentioned this pull request Dec 20, 2022
65 tasks
@seisman
Copy link
Member

seisman commented Dec 22, 2022

@PaulWessel This looks like an upstream bug in ternary. Could you please see if you can find the cause?

Here is a minimal example to reproduce the issue based on @yvonnefroehlich's tests in #2138 (comment). The example crashes with an error like:

python(62331,0x11b3eb600) malloc: *** error for object 0x60000098cc60: pointer being freed was not allocated
python(62331,0x11b3eb600) malloc: *** set a breakpoint in malloc_error_break to debug
import pandas as pd
import pygmt

df = pd.DataFrame(
    {
        "a": [0.160, 0.220, 0.090, 0.660],
        "b": [0.331, 0.625, 0.180, 0.258],
        "c": [0.509, 0.158, 0.732, 0.078],
        "d": [9.0, 39, 2, 12],
    }
)

fig = pygmt.Figure()
pygmt.makecpt(cmap="batlow", series=[0, 80, 10])
fig.ternary(
    df,
    region=[0, 100, 0, 100, 0, 100],
    width="10c",  # -JX
    style="c0.25c",
    cmap=True,
    pen="1p,black",
    frame=["aafg", "bafg", "cagf", "+givory"],
)
fig.show()

@PaulWessel
Copy link
Member

Is the sci py ecosystem up and running on Apple Silicon now? Last time (summer/spring) it was a flop.

@seisman
Copy link
Member

seisman commented Dec 22, 2022

Is the sci py ecosystem up and running on Apple Silicon now? Last time (summer/spring) it was a flop.

As I know, all PyGMT dependencies can be installed on Apple Silicon using conda.

@PaulWessel
Copy link
Member

OK, depending on time (Xmas here...) I will try to wipe whatever conda or miniconda I have and start from scratch and see if it now works.

@seisman seisman modified the milestones: 0.8.0, 0.9.0 Dec 24, 2022
@seisman
Copy link
Member

seisman commented Dec 24, 2022

I'm bumping this PR to v0.9.0 because it's likely that codes in this PR rely on upstream changes.

@PaulWessel
Copy link
Member

New miniconda for M1 installed and now things work. Ran the example above in Xcode and no crash but got some bad free memory message:

ternary (gmt_io.c:3081(gmtio_adjust_segment)): Wrongly tries to free item

which is likely related to the crash @yvonnefroehlich got (on Linux). But otherwise it worked and plotted this:

a6131bff354246398a7b40dced90b9c4.pdf

So will have to debug through the ternary call and see what is fed in and how ternary allocates (or not) memory for the data.

@seisman
Copy link
Member

seisman commented Dec 26, 2022

@michaelgrund The upstream issue has been fixed in upstream PRs GenericMappingTools/gmt#7171 and GenericMappingTools/gmt#7172 and the example will work with GMT 6.5.

To make the example work with GMT 6.3-6.4 (so that we can merge this PR), we need to take special actions for pd.DataFrame input with GMT 6.3/6.4. See #2274 for the related PR.

@michaelgrund michaelgrund marked this pull request as ready for review December 26, 2022 10:49
@michaelgrund michaelgrund marked this pull request as draft December 26, 2022 10:49
@michaelgrund michaelgrund marked this pull request as ready for review December 26, 2022 11:15
@michaelgrund michaelgrund added the needs review This PR has higher priority and needs review. label Dec 26, 2022
examples/gallery/embellishments/ternary.py Outdated Show resolved Hide resolved
examples/gallery/embellishments/ternary.py Outdated Show resolved Hide resolved
examples/gallery/embellishments/ternary.py Outdated Show resolved Hide resolved
examples/gallery/embellishments/ternary.py Outdated Show resolved Hide resolved
@seisman
Copy link
Member

seisman commented Dec 26, 2022

@michaelgrund I feel this example should be put in the "Symbols and markers" or "Base maps" categories instead.

# between ternary diagram and colorbar
fig.shift_origin(yshift="-1c")

# Add a colorbar indicating the values given in the fourth column of
Copy link
Member

Choose a reason for hiding this comment

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

Here is the plot generated using the default Figure.colorbar(frame=["x+lPermittivity"]) call. I feel the default location of the colorbar should be improved on the GMT side. What do you think?

map

Copy link
Member

Choose a reason for hiding this comment

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

I am thinking the way that ternary frame is drawn the colorer module has no way of knowing that axes was annotated so it does not add any space (or it is not in the right hidden file in the session dir). If a CLI equivalent script can be made I might be able to have a look.

Copy link
Member

Choose a reason for hiding this comment

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

Here is the CLI version:

gmt begin map
gmt makecpt -Cturbo -T0/80/10
gmt ternary @ternary.txt -R0/100/0/100/0/100 -JX6i -Sc0.1c -C -LWater/Air/Limestone \
    -Baafg+l"Water component"+u" %" -Bbafg+l"Air component"+u" %" -Bcagf+l"Limestone component"+u" %" \
    -B+givory+t"Example data from MATLAB Central"
gmt colorbar
gmt end show

map

Copy link
Member Author

Choose a reason for hiding this comment

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

Here is the plot generated using the default Figure.colorbar(frame=["x+lPermittivity"]) call. I feel the default location of the colorbar should be improved on the GMT side. What do you think?

Totally agree with you @seisman, would be great if the colorbar is placed without any direction shiftings.

@seisman seisman added final review call This PR requires final review and approval from a second reviewer and removed needs review This PR has higher priority and needs review. labels Dec 26, 2022
Co-authored-by: Yvonne Fröhlich <94163266+yvonnefroehlich@users.noreply.github.com>
@seisman seisman modified the milestones: 0.9.0, 0.8.0 Dec 27, 2022
@seisman seisman changed the title Add gallery example for ternary method Add gallery example for Figure.ternary method Dec 27, 2022
@seisman seisman merged commit a1e50ac into main Dec 27, 2022
@seisman seisman deleted the gallery-ternary branch December 27, 2022 02:15
@seisman seisman removed the final review call This PR requires final review and approval from a second reviewer label Dec 27, 2022
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants