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

beachball offsetting doesn't work for pandas/dict/ndarray input #2016

Closed
MsDannie76 opened this issue Jul 19, 2022 · 18 comments · Fixed by #2576
Closed

beachball offsetting doesn't work for pandas/dict/ndarray input #2016

MsDannie76 opened this issue Jul 19, 2022 · 18 comments · Fixed by #2576
Assignees
Labels
bug Something isn't working
Milestone

Comments

@MsDannie76
Copy link

MsDannie76 commented Jul 19, 2022

I am trying to plot focal mechanisms on a map with an offset. I’ve tried to follow the tips given here:
[ PyGMT: How to offset focal mechanism beachballs?]
but still cannot get it to work, the two beachballs in the southeast are still plotted on top of each other, although there is no error message.
FM_reg1_ex

My file contains the columns
longitude latitude depth strike dip rake magnitude plot_longitude plot_latitude
and columns are separated by tabs:

|longitude|latitude|depth|strike|dip|rake|magnitude|plot_longitude|plot_latitude|
|1.4421|51.2819|15.5|47.28|32.05|112.09|4.5|1.4421|52|
|1.3884|51.3337|17|69.84|25.88|151.52|4.5|0.75|51.3337|
|-0.055|53.648|19.3|21.33|84.92|-19.37|4.1|-0.055|53.648|
|-1.314|54.594|4.6|102.1|84.1|-162|3.1|-1.314|54.594|
FM_ISC_exampleplot.txt

I reported that issue on the GMT community forum
[Pygmt psmeca beachball - no offset despite following tips from previous post]

Full code that generated the error

import pygmt
import pandas as pd

FM_ISCex=pd.read_csv("FM_ISC_exampleplot.txt",delimiter="\t")

fig = pygmt.Figure()
fig.coast(
region="-2/2/51/55",
projection="M15c",
land="lightgray",
water="white",
borders="1/0.5p",
shorelines="1/0.5p",
frame="ag",
)

fig.meca(
spec=FM_ISCex,
convention="aki",
scale="2c",
G="red",
offset=True
)

fig.show()

Full error message

No error message, but offset given as plot_longitude and plot_latitude is not used during plotting.

System information

Please paste the output of python -c "import pygmt; pygmt.show_versions()":

pygmt installed in Anaconda Navigator, seems to be version 0.3.1
@MsDannie76 MsDannie76 added the bug Something isn't working label Jul 19, 2022
@welcome
Copy link

welcome bot commented Jul 19, 2022

👋 Thanks for opening your first issue here! Please make sure you filled out the template with as much detail as possible. You might also want to take a look at our contributing guidelines and code of conduct.

@seisman
Copy link
Member

seisman commented Jul 19, 2022

The meca() function is known to have issues/limitations in old PyGMT versions. We have fully rewritten the meca function after v0.7.0. Please try to install the PyGMT dev version using the following command:

pip install --pre --extra-index-url https://test.pypi.org/simple/ pygmt

After installing the PyGMT dev version, you'll see that it still doesn't work as expected, but at least setting spec="FM_ISC_exampleplot.txt" works.

@MsDannie76
Copy link
Author

Hi,

I upgraded to v0.7.0 . I am not sure that I understand you correctly. I don't mind reading in the file in separately, I only mind that I cannot offset the beachballs. If that also will not work in the dev-version, I'd rather stick to the normal version, or does it? (It does not seem to work in v0.7.0, either.)

@seisman
Copy link
Member

seisman commented Jul 20, 2022

The following script works for me with both PyGMT v0.7.0 and the dev version:

import pygmt
import pandas as pd

fig = pygmt.Figure()
fig.coast(
    region="-2/2/51/55",
    projection="M15c",
    land="lightgray",
    water="white",
    borders="1/0.5p",
    shorelines="1/0.5p",
    frame="ag",
)

fig.meca(
    spec="FM_ISC_exampleplot.txt", convention="aki", scale="2c", G="red", offset=True
)
fig.show()

The output image is:

focal

@MsDannie76
Copy link
Author

OK, great, thanks! It now works for me in v0.7.0 as well as long as I directly read the file using meca and not go via pandas.

@seisman seisman changed the title Pygmt psmeca beachball - no offset despite following tips from previous post beachball offsetting doesn't work for pandas input Jul 20, 2022
@yvonnefroehlich
Copy link
Member

I think the same problem occurs when passing a dictionary (dict) to spec (at least for PyGMT v0.7.0):

import pygmt

#------------------------------------------------------------------------------
# set up dictonary
dict_meca = {
    "longitude": 1,
    "latitude": 52,
    "depth": 10,
    "strike": 100,
    "dip": 50,
    "rake": 20,
    "magnitude": 5,
    "plot_longitude": 1,
    "plot_latitude": 53,
    }

#------------------------------------------------------------------------------
# create figure object
fig = pygmt.Figure()

fig.coast(
    region="-2/2/51/55",
    projection="M15c",
    land="lightgray",
    water="white",
    borders="1/0.5p",
    shorelines="1/0.5p",
    frame="ag",
    )

fig.meca(
    spec=dict_meca,
    convention="aki",
    scale="2c",
    G="red",
    offset=True,
    )

fig.show()

The beachball should be offset to latitude 53, but is plotted at latitude 52, which is the event latitude:

meca_offset_dic

@seisman seisman changed the title beachball offsetting doesn't work for pandas input beachball offsetting doesn't work for pandas/dict input Jul 20, 2022
@seisman seisman added this to the 0.8.0 milestone Jul 20, 2022
@seisman seisman self-assigned this Jul 20, 2022
@weiji14
Copy link
Member

weiji14 commented Nov 24, 2022

As a workaround for PyGMT v0.7.0, if you can set your plot_longitude and plot_latitude values to a str type (i.e. wrapping your numbers in quotes like '53'), then the beachball offset should work. E.g. using @yvonnefroehlich's code at #2016 (comment)

dict_meca = {
    "longitude": 1,
    "latitude": 52,
    "depth": 10,
    "strike": 100,
    "dip": 50,
    "rake": 20,
    "magnitude": 5,
    "plot_longitude": "1",
    "plot_latitude": "53",
}

should give:

beachball_at_53N

Notice how the beachball is now at 53N instead of 52N. For those using pandas.DataFrame inputs, there should be a way to convert your plot_longitude and plot_latitude columns to str type too using astype. Something like df["plot_longitude"].astype(dtype=str").

This will be fixed properly in #2202 (so that numeric int/float inputs will work) and should be available in the upcoming PyGMT v0.8.0. Thanks @seisman for identifying the issue!

@seisman seisman changed the title beachball offsetting doesn't work for pandas/dict input beachball offsetting doesn't work for pandas/dict/ndarray input Nov 25, 2022
@yvonnefroehlich
Copy link
Member

As a workaround for PyGMT v0.7.0, if you can set your plot_longitude and plot_latitude values to a str type (i.e. wrapping your numbers in quotes like '53'), then the beachball offset should work. E.g. using @yvonnefroehlich's code at #2016 (comment)

For me stetting the arguments for plot_longitude and plot_latitude into quotation marks (i.e. string input) does not work with PyGMT v0.7.0 and GMT 6.4.0:

Example script

import pygmt

# use dictonary to provided focal mechanism data (aki convention)
dict_meca = {
    "longitude": 0,
    "latitude": 0,
    "depth": 12,
    "strike": 330,
    "dip": 30,
    "rake": 90,
    "magnitude": 5,
    # "plot_longitude": 2,
    # "plot_latitude": 2,
    "plot_longitude": "2",  # trick use string input
    "plot_latitude": "2",
}

fig = pygmt.Figure()

fig.basemap(
    region=[-5, 5, -5, 5],
    projection="X10c",
    frame="afg",
)

fig.meca(
    spec=dict_meca,
    convention="aki",
    scale="1c",
    offset=True,
)

fig.show()

Error message

Traceback (most recent call last):

  File "C:\ProgramData\Anaconda3\envs\pygmt_env_070_640\lib\site-packages\spyder_kernels\py3compat.py", line 356, in compat_exec
    exec(code, globals, locals)

  File "c:\users\admin\c2\eigenedokumente\studium\promotion\e_gmt\00_testing\issuse_meca_offset\meca_offset_line.py", line 62, in <module>
    fig.meca(

  File "C:\ProgramData\Anaconda3\envs\pygmt_env_070_640\lib\site-packages\pygmt\helpers\decorators.py", line 585, in new_module
    return module_func(*args, **kwargs)

  File "C:\ProgramData\Anaconda3\envs\pygmt_env_070_640\lib\site-packages\pygmt\helpers\decorators.py", line 725, in new_module
    return module_func(*args, **kwargs)

  File "C:\ProgramData\Anaconda3\envs\pygmt_env_070_640\lib\site-packages\pygmt\src\meca.py", line 466, in meca
    with file_context as fname:

  File "C:\ProgramData\Anaconda3\envs\pygmt_env_070_640\lib\contextlib.py", line 119, in __enter__
    return next(self.gen)

  File "C:\ProgramData\Anaconda3\envs\pygmt_env_070_640\lib\site-packages\pygmt\clib\session.py", line 1259, in virtualfile_from_matrix
    self.put_matrix(dataset, matrix)

  File "C:\ProgramData\Anaconda3\envs\pygmt_env_070_640\lib\site-packages\pygmt\clib\session.py", line 901, in put_matrix
    raise GMTCLibError(f"Failed to put matrix of type {matrix.dtype}.")

GMTCLibError: Failed to put matrix of type <U11.

Output of pygmt.show_versions()

PyGMT information:
  version: v0.7.0
System information:
  python: 3.9.13 | packaged by conda-forge | (main, May 27 2022, 16:50:36) [MSC v.1929 64 bit (AMD64)]
  executable: C:\ProgramData\Anaconda3\envs\pygmt_env_070_640\python.exe
  machine: Windows-10-10.0.19045-SP0
Dependency information:
  numpy: 1.23.1
  pandas: 1.4.3
  xarray: 2022.6.0
  netCDF4: 1.6.0
  packaging: 21.3
  geopandas: 0.11.1
  ghostscript: 9.54.0
  gmt: 6.4.0
GMT library information:
  binary dir: C:/ProgramData/Anaconda3/envs/pygmt_env_070_640
  cores: 4
  grid layout: rows
  library path: C:/ProgramData/Anaconda3/envs/pygmt_env_070_640/Library/bin/gmt.dll
  padding: 2
  plugin dir: C:/ProgramData/Anaconda3/envs/pygmt_env_070_640/Library/bin/gmt_plugins
  share dir: C:/Program Files (x86)/gmt6/share
  version: 6.4.0

@yvonnefroehlich
Copy link
Member

An other aspect is, that the line and the small circle are not plotted or modified via the offset parameter (see
https://www.pygmt.org/dev/api/generated/pygmt.Figure.meca.html#pygmt.Figure.meca) when passing a dictionary to spec (see case (II)). It works when reading the focal mechanism data from a text file (see case (I)). In both cases a PyGMT dev version (after PR #2202 was megerd) was used.

Example script

import pygmt

#------------------------------------------------------------------------------
# (I) read focal mechanism data from input file (aki convention)
fig = pygmt.Figure()

fig.basemap(
    region=[-5, 5, -5, 5],
    projection="X10c",
    frame="afg",
)

fig.meca(
    spec="gmt_meca_doc.txt",
    scale="1c",
    offset="+p1p,green+s0.5c",  # line thickness and color, size of circle
    convention="aki",
)

fig.show()
# fig.savefig(fname="meca_offset_line_file.png")

# ------------------------------------------------------------------------------
# (II) use dictionary to provided focal mechanism data (aki convention)
dict_meca = {
    "longitude": 0,
    "latitude": 0,
    "depth": 12,
    "strike": 330,
    "dip": 30,
    "rake": 90,
    "magnitude": 5,
    "plot_longitude": 2,
    "plot_latitude": 2,
}

fig = pygmt.Figure()

fig.basemap(
    region=[-5, 5, -5, 5],
    projection="X10c",
    frame="afg",
)

fig.meca(
    spec=dict_meca,
    convention="aki",
    scale="1c",
    offset="+p1p,green+s0.5c",  # line thickness and color, size of circle
)

fig.show()
# fig.savefig(fname="meca_offset_line_dict.png")

Output figure for (I) reading a txt file (expectation)
meca_offset_line_file

Output figure for (II) using a dictionary
meca_offset_line_dict

Output of pygmt.show_versions()

PyGMT information:
  version: v0.7.1.dev170
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

@seisman
Copy link
Member

seisman commented Dec 4, 2022

For me stetting the arguments for plot_longitude and plot_latitude into quotation marks (i.e. string input) does not work with PyGMT v0.7.0 and GMT 6.4.0:

Yes, the source code of the Figure.meca() method is messy in v0.7.0 and was rewritten in #1784. The workaround works for the dev version before #2202 was merged.

An other aspect is, that the line and the small circle are not plotted or modified via the offset parameter (see
pygmt.org/dev/api/generated/pygmt.Figure.meca.html#pygmt.Figure.meca) when passing a dictionary to spec

I can confirm that this is a bug caused by

kwargs["A"] = True
.
You can make a fix if you want.

@yvonnefroehlich
Copy link
Member

An other aspect is, that the line and the small circle are not plotted or modified via the offset parameter (see
pygmt.org/dev/api/generated/pygmt.Figure.meca.html#pygmt.Figure.meca) when passing a dictionary to spec

I can confirm that this is a bug caused by

kwargs["A"] = True

.
You can make a fix if you want.

Done via PR #2226.

@yvonnefroehlich
Copy link
Member

Can we close this issue? It should be now (hopefully) fixed by #2202 and Figure.meca: Fix line and circle of offset parameter for dict/pandas input #2226.

@seisman
Copy link
Member

seisman commented Dec 20, 2022

Can we close this issue? It should be now (hopefully) fixed by #2202 and Figure.meca: Fix line and circle of offset parameter for dict/pandas input #2226.

Beachball offsetting may still fail for ndarray input. Need some time to test.

@yvonnefroehlich
Copy link
Member

yvonnefroehlich commented Dec 20, 2022

Can we close this issue? It should be now (hopefully) fixed by #2202 and Figure.meca: Fix line and circle of offset parameter for dict/pandas input #2226.

Beachball offsetting may still fail for ndarray input. Need some time to test.

Thanks! I see the updated issue title. Hm, then bump this back to v0.9.0 🙂?

@seisman
Copy link
Member

seisman commented Dec 21, 2022

I'll see if I can finish it before v0.8.0.

@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 issue to v0.9.0 because beachball offsetting for ndarray input is more tricky than I initially thought so I can't finish it soon.

@weiji14
Copy link
Member

weiji14 commented Mar 6, 2023

I'm bumping this issue to v0.9.0 because beachball offsetting for ndarray input is more tricky than I initially thought so I can't finish it soon.

Do you have time to work on this before end of March 2023? Or should we bump this to PyGMT v0.10.0?

@seisman
Copy link
Member

seisman commented Mar 6, 2023

I'll give it another try in the following week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
4 participants