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

Copy pygmt.Figure() instance or object to a new variable and keep the initial variable as is #3645

Open
yvonnefroehlich opened this issue Nov 24, 2024 · 9 comments
Labels
discussions Need more discussion before taking further actions feature request New feature wanted longterm Long standing issues that need to be resolved

Comments

@yvonnefroehlich
Copy link
Member

yvonnefroehlich commented Nov 24, 2024

Copying a pygmt.Figure() instance or object to a new variable can be useful, e.g., within a Jupyter notebook for re-running cells with different arguments passed to the parameters to test different visualizations. However, this seems to be not straight forward. In the example below, I would like to achieve that fig1 remains as is after adding features to fig2. Neither running fig2 = fig1 nor running fig2 = copy.deepcopy(fig1) before changing fig2 works as expected. Maybe there is a relationship to continuing the GMT session and not creating a new one?

Related to: GenericMappingTools/agu24workshop#8 (comment), GenericMappingTools/agu24workshop#8 (comment)

import pygmt

size = 5

fig1 = pygmt.Figure()
fig1.basemap(projection="X5c", region=[-5, 5, -5, 5], frame=True)
fig1.show()

fig2 = fig1
# OR (both does not work as expected)
# fig2 = copy.deepcopy(fig1)
fig2.plot(x=0, y=0, style="c1c")
fig2.show()

fig1.show()  # Now fig1 also contains the circle and is identical to fig2
fig1 fig2 fig1
fig1_first fig2 fig1_second
@yvonnefroehlich yvonnefroehlich added question Further information is requested feature request New feature wanted discussions Need more discussion before taking further actions labels Nov 24, 2024
@seisman
Copy link
Member

seisman commented Nov 26, 2024

This feature is difficult to implement. The main reason is that, GMT stores the half-baked PS file, gmt.history, gmt.conf and even inset/subplot settings in temporary files. To implement what you expect with the syntax like fig1 = fig2.copy(), we need to copy fig1-related files and make necessary changes to ensure it works for fig2, which means we have to know all the details about GMT and even have to use GMT's low-level, private functions.

@seisman seisman added longterm Long standing issues that need to be resolved and removed question Further information is requested labels Nov 26, 2024
@joa-quim
Copy link
Member

Yes, modern mode is quite tricky and does not lets us almost no liberty to inovate. However, I am a bit confused with this behavior, but for another reason.

When you call fig1.show() shouldn't it close the PS file and delete the temporary sessions dir? How come that you can still append to fig1 if, besides surviving to show(), it had to be closed order to be displayed?

@seisman
Copy link
Member

seisman commented Nov 29, 2024

When you call fig1.show() shouldn't it close the PS file and delete the temporary sessions dir? How come that you can still append to fig1 if, besides surviving to show(), it had to be closed order to be displayed?

We're doing this in PyGMT:

gmt begin
    gmt figure figname -    # Need to pass '-' as a special format
    gmt basemap ...
    gmt coast ...

    gmt psconvert ...
    open figname.png

    gmt grdimage ...

    gmt psconvert ...
    open figname.png

gmt end

When calling Figure.show, we call psconvert to convert the PS file into the desired format and then open it in an external viewer. The PS file is still there until we call gmt end. That's why we can append more layers even after calling Figure.show.

@joa-quim
Copy link
Member

But if you call psconvert before gmt end the file is not yet closed and you should get the error

psconvert [ERROR]: lixo.ps: GMT PS format detected but file is not finalized. Maybe a -K in excess? No output created.

What am I missing?

@seisman
Copy link
Member

seisman commented Nov 29, 2024

Maybe you're not in modern mode? Try this one:

gmt begin
  gmt figure map -
  gmt basemap -R0/10/0/10 -JX10c -Baf
  gmt psconvert -A -P -Tg -Ffig1

  gmt basemap -R0/5/0/5 -JX10c -Baf -X10c
  gmt psconvert -A -P -Tg -Ffig2
gmt end

@joa-quim
Copy link
Member

Hmm, I see. I guess I had forgotten or didn't even know that we could do that in modern mode. I barely use it, except for the insets in Julia where fish inside some of the tmp files to learn the coordinates where to put the inset. It's a crazy mixed scheme between modern and classic.

@seisman
Copy link
Member

seisman commented Nov 29, 2024

@joa-quim
Copy link
Member

Ah, so it was a forgotten thing since psconvert.c is one of the codes that I visit more often.

And speaking of which, it would be nice if you could use the psconvert-no-file-dup branch (the one where psconvert edits the ps file directly instead of making a copy) in your PyGMT tests. I've been using it in Julia and found no problems so far.

@seisman
Copy link
Member

seisman commented Nov 29, 2024

And speaking of which, it would be nice if you could use the psconvert-no-file-dup branch (the one where psconvert edits the ps file directly instead of making a copy) in your PyGMT tests. I've been using it in Julia and found no problems so far.

OK. Will give it a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussions Need more discussion before taking further actions feature request New feature wanted longterm Long standing issues that need to be resolved
Projects
None yet
Development

No branches or pull requests

3 participants