how to save figure using pyscript

Issue

As title mentioned, actually i’m a rookie for html and css. So how i can use savefig or other methods to save plot files using matplotlib

<html>
  <body style="margin: 25px 75px 25px 75px;">
    <div class="p-5 text-center bg-light">
      <p>Quick Draw by<a href="https://github.com/ELongking"> <span>Longking</span> </a></p>
      <p><a href="https://github.com/pyscript/pyscript"><span>PyScript</span></a> is a very new framework, it needs a few seconds to load...</p>
      <h3>If you want to use it again, you need to refresh the page</h3>
    </div>
    
    <div class="container" id="test-plot">
    <p>Please enter your equation which is need to be drawn</p>
    <input id="eq" type="text" width="20" placeholder="y=2*x+sqrt(x)">
    <br>
    <p>Set the range of x coordinate</p>
    <input id="ra" type="text" width="20" placeholder="-5,5">
    <br>

    <p>Save or not</p>
    <input id="save" type="text" width="20" placeholder="yes or no">
    <br>

    <button id="but" style="margin-top: 10px;margin-bottom: 10px;" type="button" pys-onClick="main">
  Generate</button>
    </div>
    <py-script>

      from numpy import *
      from matplotlib import pyplot as plt, style as sty
      from js import console, document
      
      def main(*args,**kwargs):

        eq=document.getElementById("eq").value
        ra=document.getElementById("ra").value
        save=document.getElementById("save").value

        main_eq=eq.split('=')[1]
        if ra.find(',')>0:
          xmin,xmax=float(ra.split(',')[0]),float(ra.split(',')[1])
        else:
          xmin,xmax=-5,5

        x=linspace(xmin,xmax,1000)
        y=eval(main_eq)
        
        sty.use('seaborn-paper')
        fig, ax = plt.subplots()
        ax.plot(x, y,'--')

        if save=="yes":
          plt.savefig(r"D:\result.png",dpi=600)
        pyscript.write("test-plot",fig)

    </py-script>
    </div>
  </body>
</html>

I want to save figure to result.png in D drive, but it didn’t work for me. Thanks for your solution.

Solution

The following line of code writes to the browser’s virtual file system and not to the user’s desktop file system:

plt.savefig(r"D:\result.png",dpi=600)

The solution is to use the browser file system API to write to the user’s desktop file system.

First, save the data as a BytesIO and call a function to perform the file save:

buf = io.BytesIO()
plt.savefig(buf, format='png')
await save_file(buf)

The file save function will interface with the browser’s file system:

import asyncio
from js import console, document, window, Blob
from pyodide import to_js

async def save_file(buf):
        try:
                # Read and convert to a JavaScript array
                buf.seek(0)
                content = to_js(buf.read())

                # Create a JavaScript Blob and set the Blob type as a PNG
                b = Blob.new([content], {type: "image/png"})

                # Perform the actual file system save 
                fileHandle = await window.showSaveFilePicker()
                file = await fileHandle.createWritable()
                await file.write(b)
                await file.close()
        except Exception as e:
                console.log('Exception: ' + str(e))
                return

I wrote an article that helps explain interfacing with the browser’s file system:

Pyscript: Files and File Systems – Part 2

Answered By – John Hanley

Answer Checked By – Katrina (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.