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 sage.misc.latex.pdf to save the image of objects to pdf #38339

Merged
merged 1 commit into from
Oct 12, 2024

Conversation

kwankyu
Copy link
Collaborator

@kwankyu kwankyu commented Jul 8, 2024

Hence

sage: from sage.misc.latex import pdf
sage: pdf(pi, 'test.pdf')

works. This is a companion to the existing sage.misc.latex.png, which saves png image of objects. Of course, pdf image is scalable and hence more suitable for inclusion into latex documents.

Also we fix it that view() sporadically fails on mac because the temporary file is removed before the viewer opens the file. For example,

sage: view(pi)  # show pi

Thus after this PR, the temporary file is removed when the viewer (Preview app on mac, not the window showing the image) closes. This behavior is consistent with that on linux.

📝 Checklist

  • The title is concise and informative.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation and checked the documentation preview.

⌛ Dependencies

@kwankyu kwankyu changed the title Add pdf() Add sage.misc.latex.pdf to save sage objects to pdf file Jul 8, 2024
Copy link

github-actions bot commented Jul 8, 2024

Documentation preview for this PR (built with commit 841298f; changes) is ready! 🎉
This preview will update shortly after each push to this PR.

@kwankyu kwankyu changed the title Add sage.misc.latex.pdf to save sage objects to pdf file Add sage.misc.latex.pdf to save the pdf image of objects Jul 8, 2024
@kwankyu kwankyu changed the title Add sage.misc.latex.pdf to save the pdf image of objects Add sage.misc.latex.pdf to save the image of objects to pdf Jul 8, 2024
@kwankyu kwankyu marked this pull request as ready for review July 8, 2024 12:54
@mkoeppe mkoeppe requested a review from seblabbe July 10, 2024 01:20
@mkoeppe mkoeppe requested a review from orlitzky August 4, 2024 20:17
@orlitzky
Copy link
Contributor

orlitzky commented Aug 4, 2024

sleep(5) will fail randomly, why replace the explicit synchronization?

@orlitzky
Copy link
Contributor

orlitzky commented Aug 4, 2024

The report at https://groups.google.com/g/sage-support/c/YfyaZxc8Z6k has nothing to do with the viewer opening too fast. LaTeX failed to build the PDF in the first place.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 5, 2024

The report at https://groups.google.com/g/sage-support/c/YfyaZxc8Z6k has nothing to do with the viewer opening too fast. LaTeX failed to build the PDF in the first place.

No. The PDF was built. This code

    # Return immediately but only clean up the temporary file after
    # the viewer has closed. This function is synchronous and waits
    # for the process to complete...
    def run_viewer():
        run([viewer, output_file], capture_output=True)
        tmp.cleanup()    

does not work as the comment promised. This is what happens: The viewer "opens" (that is, the operating system successfully launched the viewer). Then tmp.cleanup() cleans up the temporary PDF file, before the viewer opens up the PDF file!. The viewer says "no pdf file".

We have to give the viewer enough time to really open the PDF file after it launched. There is no way to detect when the viewer has opened the file. 5 seconds seems enough.

@orlitzky
Copy link
Contributor

orlitzky commented Aug 5, 2024

The error ! ==> Fatal error occurred, no output PDF file produced! comes from LaTeX, not sage. You can run pdflatex -halt-on-error on a file containing junk and that's what it will display.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 5, 2024

I don't know the reporter's system. He says "Latex does work though". So I guess that the message is from the viewer.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 5, 2024

By the way, I also experience this "no pdf file" symptom on my system (mac). Why I prepared this PR :-)

@orlitzky
Copy link
Contributor

orlitzky commented Aug 5, 2024

He tells you his system. Like I said, you can run pdflatex yourself and see exactly where the error comes from. You're trying to fix something that isn't broken.

There may be a problem on mac, but I can't test. You should probably figure out why the current approach doesn't work. Or just add a special case for mac if you don't feel like it. But don't make the situation worse for everyone else because nothing is broken on linux.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 5, 2024

Like I said, you can run pdflatex yourself and see exactly where the error comes from. You're trying to fix something that isn't broken.

I see what you mean. I cannot be sure on the reporter's case.

There may be a problem on mac, but I can't test. You should probably figure out why the current approach doesn't work.

For me, the symptom is sporadic. If the viewer opens up the file quickly enough, no problem. Sometimes not. Maybe dependent on the pdf file size...

Or just add a special case for mac if you don't feel like it.

From the reporter's case, I guessed the symptom can also happen on linux, perhaps depending on the latex system or pdf viewer.

But don't make the situation worse for everyone else because nothing is broken on linux.

OK. No problem. I can wait for input from other people.

@dimpase
Copy link
Member

dimpase commented Aug 5, 2024

how can this happen at all? view is one of many commands using a temporary file, but the typical issue is that these files are left uncleaned

@dimpase
Copy link
Member

dimpase commented Aug 5, 2024

For me, the symptom is sporadic. If the viewer opens up the file quickly enough, no problem. Sometimes not. Maybe dependent on the pdf file size...

Do you by any chance have an antivirus or some other spyware^H^H^^ thing like this installed on your mac? Often that's the case with employer-issued machines...

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 5, 2024

No.

I explained how it happens above: #38339 (comment)

There is nothing strange why it happens.

@dimpase
Copy link
Member

dimpase commented Aug 5, 2024

No.

I explained how it happens above: #38339 (comment)

There is nothing strange why it happens.

Do you mean it's a bug in CPython on macOS? Could be, of course, in how threads are handled, but this is not something that should be fixed by adding dodgy extra waiting times, unconditionally on the platform.

Or, perhaps how run_viewer is launched:

    from threading import Thread
    t = Thread(target=run_viewer)
    t.daemon = True
    t.start()

does not work correctly on macOS?

@dimpase
Copy link
Member

dimpase commented Aug 5, 2024

reading https://docs.python.org/3/library/threading.html does not convince me about the validity of the syncronisation via t.daemon used in Sage. It seems to be for something else.

@orlitzky
Copy link
Contributor

orlitzky commented Aug 5, 2024

The daemon flag wasn't for synchronization per se. Without it, sage would refuse to exit while the viewer was still open; sage was waiting for the view/cleanup thread to finish. That page says,

A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property or the daemon constructor argument.

Adding it does allow sage to quit while the viewer is open.

@dimpase
Copy link
Member

dimpase commented Aug 5, 2024

it seems to be the default behaviour of open on macOS is not to wait until the process ends.
However, one can do open -W to let it wait until it completes.

    -W  Causes open to wait until the applications it opens (or that were already open) have exited.  Use with the -n flag to allow open to function as an appropriate app for the $EDITOR
         environment variable.

This way, run() would end only when the viewer completes, and so the files can be cleaned up safely.

@orlitzky
Copy link
Contributor

orlitzky commented Aug 5, 2024

it seems to be the default behaviour of open on macOS is not to wait until the process ends. However, one can do open -W to let it wait until it completes.

This is the way e.g. exo-open works on linux, too. But if adding -W on macos makes the problem go away that's still a great solution.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 5, 2024

Adding -W works. That is, tmp.cleanup() is executed after Preview (the default pdf viewer on macos run by open) closes (this is closing the application, not just closing a window showing the pdf file).

On the other hand, If I end sage session without closing Preview, the thread seems gone and tmp.cleanup() is not executed. I am not sure if the temporary file was cleaned up in this case...

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 6, 2024

Now I am using Dima's solution open -W. It is working well on my side.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 13, 2024

Anything else?

The problem of not cleaning up the temporary file if sage session ends while the viewer is open persists, before and after the PR. This PR fixes only the problem on mac that the viewer sporadically crashes because the temporary file is cleaned up too soon.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 13, 2024

and of course, we get a new pdf(obj) command.

@dimpase
Copy link
Member

dimpase commented Aug 13, 2024

Anything else?

The problem of not cleaning up the temporary file if sage session ends while the viewer is open persists, before and after the PR. This PR fixes only the problem on mac that the viewer sporadically crashes because the temporary file is cleaned up too soon.

see #38339 (comment)

@kwankyu
Copy link
Collaborator Author

kwankyu commented Aug 13, 2024

I did. So?

I followed the uncontroversial approach of adding -W to solve the problem on mac. There is no other change regarding the temporary files.

@jhpalmieri
Copy link
Member

Would it make sense to split the open -W fix into a separate PR?

@kwankyu
Copy link
Collaborator Author

kwankyu commented Sep 30, 2024

Why?

In addition to that, this PR enables

sage: from sage.misc.latex import pdf
sage: pdf(pi, 'test.pdf')

There is no negative review about this.

@jhpalmieri
Copy link
Member

Why?

In addition to that, this PR enables

sage: from sage.misc.latex import pdf
sage: pdf(pi, 'test.pdf')

There is no negative review about this.

(a) It seems to often be a good idea for a PR to do one thing, not several independent things. Easier for reviewing, easier for merging. (b) In particular, the open -W change fixes a bug and so is somewhat urgent, and it might be faster to get it merged if it's separated from the other part. Or alternatively, it might be faster to get the other contributions merged if the open -W part is the only aspect where there is any disagreement.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Sep 30, 2024

(a) It seems to often be a good idea for a PR to do one thing, not several independent things. Easier for reviewing, easier for merging.

In practice, that argument is reasonable only when the PR is big, and developers often combine small things to the main thing in their PRs.

(b) In particular, the open -W change fixes a bug and so is somewhat urgent, and it might be faster to get it merged if it's separated from the other part.

The "bug" has been in sage for years. I have lived with it. There is nothing urgent for such an old bug. I am not in hurry.

The bug fix is a small thing of this PR. If anyone is in hurry and wants to merge it in quickly, please open a separate PR. It is just one-liner. I am not willing to do it at this moment.

Or alternatively, it might be faster to get the other contributions merged if the open -W part is the only aspect where there is any disagreement.

Though DIma made me confused in #38339 (comment), I think there is no disagreement about that. The fix is not perfect on mac (because of how Preview works), but the situation gets better.

The main thing of this PR is also small. Please review the main thing.

@dimpase
Copy link
Member

dimpase commented Sep 30, 2024

in pdf() function, the engine= doc is a bit misleading. It is only formally None, as it in fact gets immediately assigned a value from preferences.
Can you say so in the doc?

@kwankyu
Copy link
Collaborator Author

kwankyu commented Oct 1, 2024

Right. Done.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Oct 1, 2024

.... The fix is not perfect on mac (because of how Preview works), but the situation gets better.

Let me elaborate on this. On mac, this happens when view(image) runs: Preview app opens an window showing the image from a temporary file. The temporary file is supposed to be deleted when the Preview app closes. But a mac user just closes the window containing the image, and the Preview app still lingers. Hence the temporary file won't be deleted until the user closes the Preview app. If the user is like me, she will close sage long before she would close the Preview app (perhaps when she turns the power off :-). I don't know what happens to the temporary file, since sage was closed before the Preview app...

@kwankyu
Copy link
Collaborator Author

kwankyu commented Oct 5, 2024

.... The fix is not perfect on mac (because of how Preview works), but the situation gets better.

... I don't know what happens to the temporary file, since sage was closed before the Preview app...

I experimented more. The temporary file is removed when sage is closed, even if the Preview app is still running. Perfect!

@dimpase
Copy link
Member

dimpase commented Oct 5, 2024

I'd happy to give it a positive review.

@kwankyu
Copy link
Collaborator Author

kwankyu commented Oct 5, 2024

Thanks!

vbraun pushed a commit to vbraun/sage that referenced this pull request Oct 9, 2024
…s to pdf

    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

Hence
```sage
sage: from sage.misc.latex import pdf
sage: pdf(pi, 'test.pdf')
```
works. This is a companion to the existing `sage.misc.latex.png`, which
saves png image of objects. Of course, pdf image is scalable and hence
more suitable for inclusion into latex documents.

Also we fix it that `view()` sporadically fails on mac because the
temporary file is removed before the viewer opens the file. For example,
```sage
sage: view(pi)  # show pi
```
Thus after this PR, the temporary file is removed when the viewer
(`Preview` app on mac, not the window showing the image) closes. This
behavior is consistent with that on linux.

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#38339
Reported by: Kwankyu Lee
Reviewer(s): Dima Pasechnik
vbraun pushed a commit to vbraun/sage that referenced this pull request Oct 9, 2024
    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

Fixes sagemath#38745

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->

sagemath#38339
    
URL: sagemath#38764
Reported by: Kwankyu Lee
Reviewer(s): Travis Scrimshaw
vbraun pushed a commit to vbraun/sage that referenced this pull request Oct 11, 2024
    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

Fixes sagemath#38745

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->

sagemath#38339
    
URL: sagemath#38764
Reported by: Kwankyu Lee
Reviewer(s): Travis Scrimshaw
@vbraun vbraun merged commit 6b02856 into sagemath:develop Oct 12, 2024
19 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants