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

Allow support for saving png figure in py3Dmol #380

Closed
psychemedia opened this issue Aug 13, 2018 · 12 comments
Closed

Allow support for saving png figure in py3Dmol #380

psychemedia opened this issue Aug 13, 2018 · 12 comments

Comments

@psychemedia
Copy link

It would be useful if https://github.com/3dmol/3Dmol.js/blob/master/py3Dmol/py3Dmol/__init__.py was modified to allow the return of the image data URI as well as providing an image output for notebooks?

Crudely, perhaps something like:

    def png(self, data=False):
        '''output png image of viewer, which must already be instantiated'''
        if not self.uniqueid:
            raise AssertionError('Must instantiate viewer before generating image.')
        #Return data if that's the output requested
        if data: return viewer_{0}.pngURI()
        script = '''<img id="img_{0}">
            <script>
            var png = viewer_{0}.pngURI()
            $('#img_{0}').attr('src', png)
            </script>'''.format(self.uniqueid)
        return IPython.display.publish_display_data({'application/3dmoljs_load.v0':script, 'text/html': script})
@dkoes
Copy link
Contributor

dkoes commented Aug 13, 2018

Calling pngURI directly on the viewer object should work, yes?

@psychemedia
Copy link
Author

I think so, if you can get hold of the viewer object?

I spent a chunk of time trying to see if I could pull things from the cell output but got nowhere. I could capture cell output, buut that just returns javascript that references various js objects. The above recipe (which requires a fork or an update) was only way I could think of getting the data URI?

If you have any other insights into what I could call from an .ipynb code cell to get a representation of the image, that would be really useful...

@dkoes
Copy link
Contributor

dkoes commented Aug 14, 2018

Right, I wasn't thinking it through. There is no communication from JavaScript back to python. You'd have to use the jupyter comms mechanism to do that, which py3Dmol very explicitly avoids (should never need a running kernel for py3Dmol notebooks to work).

I don't see how your provided recipe could work as it seems to mix python and javascript incompatibly. Does it work?

@psychemedia
Copy link
Author

psychemedia commented Aug 14, 2018

Doh - and I'd misread - the viewer_{0}.pngURI() thing is inside the js context isn't it? Sorry, not concentrating...

Would it be possible to just run the js to get the data URI, return the data rather than the img html, and capture the returned data? (Or is there perhaps an easier way to run the js and get the response back directory into a python variable?)

Below doesn't work, does it, because all we capture is the HTML? How do ipywidgets pass values back from HTML context to Python?

Maybe:

if data: 
            script='''<script>
            var pngdata = viewer_{0}.pngURI()
            </script>'''.format(self.uniqueid)
           #But then how do we actually see the value of pngdata?
            return IPython.display.publish_display_data({'text/html': script})

and then in the notebook, after displaying the viewer, in a new cell make the call and capture the output:

%%capture capdata
x.png(data=True)

and then in another cell use the captured data:

#image data URI in here?
capdata.outputs[0].data

@dkoes
Copy link
Contributor

dkoes commented Aug 14, 2018

I'm pretty sure %capture is only for python code. If you want to get values from javascript into python, you need to use the comms mechanism:
http://jupyter-notebook.readthedocs.io/en/latest/comms.html

@psychemedia
Copy link
Author

See related issue on a generic widget2png idea: jupyter-widgets/ipywidgets#2280

@scottwsides
Copy link

I have a py3Dmol viewer object in my notebook. Forgive me for not following the above discussion... but can someone tell me how to go from py3DmolViewer object ---> png File explicitly? Everything I've tried and guessed at has not worked

@dkoes
Copy link
Contributor

dkoes commented Jan 2, 2020

What happens when you call png on the view object? This works for me.

@scottwsides
Copy link

scottwsides commented Jan 2, 2020 via email

@dkoes
Copy link
Contributor

dkoes commented Jan 2, 2020

You can right click on the image to download it. If your goal is to automate the generation of images within python, this isn't the right tool. I recommend pymol.

@scottwsides
Copy link

Thanks for the info. So pymol is still a wrapper around 3Dmol.js? The interface is more-or-less the same as py3Dmol?

@dkoes
Copy link
Contributor

dkoes commented Jan 2, 2020

No, PyMOL is the open source software originally developed by Warren L. DeLano that is currently owned and supported by Schroedinger.
https://pymol.org/2/

You should be able to install the open source version using your favorite package manager.

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

No branches or pull requests

4 participants