skip to Main Content

I would like to display a radar chart with JavaScript by using the element values from PyScript. However, I could not display the chart after trying my code.

I have tried:

<!DOCTYPE html>
<html>
    <head>
    <meta charset="utf-8" />
    <title>
    Read CSV with Pandas using PyScript
    </title>
    <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
    <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    <script defer src="https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
    <script src="echarts.js"></script>
    </head>
    <body>
    <p id="csv"></p>
        <py-config type="json">
            {
              "packages": ["pandas"]
            }
        </py-config>
        <py-script>
            import pandas as pd
            import numpy as np
            from pyodide.http import open_url
            #from js import createObject
            #from pyodide.ffi import create_proxy
            #createObject(create_proxy(globals()), "pyodideGlobals")
            url_content = open_url("https://raw.githubusercontent.com/linnlim/Laptop/main/Laptop.csv")
            df = pd.read_csv(url_content)
            
            L1_VRAM = df['VRAM'].loc[df.index[0]]
            L2_VRAM = df['VRAM'].loc[df.index[1]]
            L3_VRAM = df['VRAM'].loc[df.index[2]]
            
            L1_RAM = df['RAM'].loc[df.index[0]]
            L2_RAM = df['RAM'].loc[df.index[1]]
            L3_RAM = df['RAM'].loc[df.index[2]]
            
            L1_ROM = df['ROM'].loc[df.index[0]]
            L2_ROM = df['ROM'].loc[df.index[1]]
            L3_ROM = df['ROM'].loc[df.index[2]]
            
            L1_CPU = df['CPU'].loc[df.index[0]]
            L2_CPU = df['CPU'].loc[df.index[1]]
            L3_CPU = df['CPU'].loc[df.index[2]]
            
            L1_Price = df['Price'].loc[df.index[0]]
            L2_Price = df['Price'].loc[df.index[1]]
            L3_Price = df['Price'].loc[df.index[2]]
            
            
            def L1_VRAM():
                return df['VRAM'].loc[df.index[0]]
            def L2_VRAM():
                return df['VRAM'].loc[df.index[1]]
            def L3_VRAM():
                return df['VRAM'].loc[df.index[2]]
                
            def L1_RAM():
                return df['RAM'].loc[df.index[0]]
            def L2_RAM():
                return df['RAM'].loc[df.index[1]]
            def L3_RAM():
                return df['RAM'].loc[df.index[2]]
                
            def L1_ROM():
                return df['ROM'].loc[df.index[0]]
            def L2_ROM():
                return df['ROM'].loc[df.index[1]]
            def L3_ROM():
                return df['ROM'].loc[df.index[2]]
                
            def L1_CPU():
                return df['CPU'].loc[df.index[0]]
            def L2_CPU():
                return df['CPU'].loc[df.index[1]]
            def L3_CPU():
                return df['CPU'].loc[df.index[2]]
                
            def L1_Price():
                return df['Price'].loc[df.index[0]]
            def L2_Price():
                return df['Price'].loc[df.index[1]]
            def L3_Price():
                return df['Price'].loc[df.index[2]]
                
            csv = Element('csv')
            csv.write(L3_CPU())
        </py-script>
        <div id="main" style="width: 600px;height:400px;"></div>
        <script type="text/javascript">
        var chartDom = document.getElementById('main');
        var myChart = echarts.init(chartDom);
        var option;
        console.log(`In Python right now, x = ${pyscript.interpreter.globals.get('L1_CPU')})
        option = {
          title: {
            text: 'Basic Radar Chart'
          },
          legend: {
            data: ['Laptop 1', 'Laptop 2', 'Laptop 3']
          },
          radar: {
            // shape: 'circle',
            indicator: [
              { name: 'VRAM', max: 10 },
              { name: 'RAM', max: 10 },
              { name: 'ROM', max: 10 },
              { name: 'CPU', max: 10 },
              { name: 'Price', max: 10 }
            ]
          },
          series: [
            {
              name: 'Laptop Specification',
              type: 'radar',
              data: [
                {
                  value: [${pyscript.interpreter.globals.get('L1_VRAM')}, ${pyscript.interpreter.globals.get('L1_RAM')}, ${pyscript.interpreter.globals.get('L1_ROM')}, ${pyscript.interpreter.globals.get('L1_CPU')}, ${pyscript.interpreter.globals.get('L1_Price')}],
                  name: 'Laptop 1'
                },
                {
                  value: [${pyscript.interpreter.globals.get('L2_VRAM')}, ${pyscript.interpreter.globals.get('L2_RAM')}, ${pyscript.interpreter.globals.get('L2_ROM')}, ${pyscript.interpreter.globals.get('L2_CPU')}, ${pyscript.interpreter.globals.get('L2_Price')}],
                  name: 'Laptop 2'
                },
                {
                  value: [${pyscript.interpreter.globals.get('L3_VRAM')}, ${pyscript.interpreter.globals.get('L3_RAM')}, ${pyscript.interpreter.globals.get('L3_ROM')}, ${pyscript.interpreter.globals.get('L3_CPU')}, ${pyscript.interpreter.globals.get('L3_Price')}],
                  name: 'Laptop 3'
                }
              ]
            }
          ]
        };
        

        option && myChart.setOption(option);
        </script>
    </body>
</html>

I am expecting to display a radar chart with 3 polygons of the laptop specifications (VRAM, RAM, ROM, CPU, Price).
I think the problem is with the ${pyscript.interpreter.globals.get()} function.

Thanks in advance.

2

Answers


  1. Chosen as BEST ANSWER
    <!DOCTYPE html>
    <html>
        <head>
        <meta charset="utf-8" />
        <title>
        Read CSV with Pandas using PyScript
        </title>
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
        <script defer src="https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <body>
            <py-config type="json">
                {
                "packages": ["pandas"]
                }
            </py-config>
            <py-script>
                import pandas as pd
                import numpy as np
                from pyodide.http import open_url
                url_content = open_url("https://raw.githubusercontent.com/linnlim/Laptop/main/Laptop.csv")
                df = pd.read_csv(url_content)
    
                L1_VRAM = df['VRAM'].loc[df.index[0]]
                L2_VRAM = df['VRAM'].loc[df.index[1]]
                L3_VRAM = df['VRAM'].loc[df.index[2]]
    
                L1_RAM = df['RAM'].loc[df.index[0]]
                L2_RAM = df['RAM'].loc[df.index[1]]
                L3_RAM = df['RAM'].loc[df.index[2]]
    
                L1_ROM = df['ROM'].loc[df.index[0]]
                L2_ROM = df['ROM'].loc[df.index[1]]
                L3_ROM = df['ROM'].loc[df.index[2]]
    
                L1_CPU = df['CPU'].loc[df.index[0]]
                L2_CPU = df['CPU'].loc[df.index[1]]
                L3_CPU = df['CPU'].loc[df.index[2]]
    
                L1_Price = df['Price'].loc[df.index[0]]
                L2_Price = df['Price'].loc[df.index[1]]
                L3_Price = df['Price'].loc[df.index[2]]
    
    
                def L1_VRAM():
                    return df['VRAM'].loc[df.index[0]]
                def L2_VRAM():
                    return df['VRAM'].loc[df.index[1]]
                def L3_VRAM():
                    return df['VRAM'].loc[df.index[2]]
    
                def L1_RAM():
                    return df['RAM'].loc[df.index[0]]
                def L2_RAM():
                    return df['RAM'].loc[df.index[1]]
                def L3_RAM():
                    return df['RAM'].loc[df.index[2]]
    
                def L1_ROM():
                    return df['ROM'].loc[df.index[0]]
                def L2_ROM():
                    return df['ROM'].loc[df.index[1]]
                def L3_ROM():
                    return df['ROM'].loc[df.index[2]]
    
                def L1_CPU():
                    return df['CPU'].loc[df.index[0]]
                def L2_CPU():
                    return df['CPU'].loc[df.index[1]]
                def L3_CPU():
                    return df['CPU'].loc[df.index[2]]
    
                def L1_Price():
                    return df['Price'].loc[df.index[0]]
                def L2_Price():
                    return df['Price'].loc[df.index[1]]
                def L3_Price():
                    return df['Price'].loc[df.index[2]]
                js.startScript()
            </py-script>
            <div id="main" style="width: 600px;height:400px;"></div>
    
            <script>
            function startScript()
            {
              setTimeout(makeChart, 0); // let the sequence that called startScript complete
            }
    
            function makeChart()
            {
              var chartDom = document.getElementById('main');
              var myChart = echarts.init(chartDom);
              var option;
              console.log(`In Python right now, x = ${pyscript.interpreter.globals.get('L1_CPU')()}`)
              option = {
                title: {
                  text: 'Basic Radar Chart'
                },
                legend: {
                  data: ['Laptop 1', 'Laptop 2', 'Laptop 3']
                },
                radar: {
                  // shape: 'circle',
                  indicator: [{
                      name: 'VRAM',
                      max: 10
                    },
                    {
                      name: 'RAM',
                      max: 10
                    },
                    {
                      name: 'ROM',
                      max: 10
                    },
                    {
                      name: 'CPU',
                      max: 10
                    },
                    {
                      name: 'Price',
                      max: 10
                    }
                  ]
                },
                series: [{
                  name: 'Laptop Specification',
                  type: 'radar',
                  data: [{
                      value: [
                        Number(pyscript.interpreter.globals.get('L1_VRAM')()),
                        Number(pyscript.interpreter.globals.get('L1_RAM')()),
                        Number(pyscript.interpreter.globals.get('L1_ROM')()),
                        Number(pyscript.interpreter.globals.get('L1_CPU')()),
                        Number(pyscript.interpreter.globals.get('L1_Price')())
                      ],
                      name: 'Laptop 1'
                    },
                    {
                      value: [
                        Number(pyscript.interpreter.globals.get('L2_VRAM')()),
                        Number(pyscript.interpreter.globals.get('L2_RAM')()),
                        Number(pyscript.interpreter.globals.get('L2_ROM')()),
                        Number(pyscript.interpreter.globals.get('L2_CPU')()),
                        Number(pyscript.interpreter.globals.get('L2_Price')())
                      ],
                      name: 'Laptop 2'
                    },
                    {
                      value: [
                        Number(pyscript.interpreter.globals.get('L3_VRAM')()),
                        Number(pyscript.interpreter.globals.get('L3_RAM')()),
                        Number(pyscript.interpreter.globals.get('L3_ROM')()),
                        Number(pyscript.interpreter.globals.get('L3_CPU')()),
                        Number(pyscript.interpreter.globals.get('L3_Price')())
                      ],
                      name: 'Laptop 3'
                    }
                  ]
                }]
              };
    
              option && myChart.setOption(option);
            }
            </script>
        </body>
    </html>
    

  2. There are some minor issues with the code you posted:

    • I’m not sure why you wrapped the python values in argumentless functions, but since they are functions, you have to invoke (call) them in javascript too (actually what you call is the proxy returned by get):
      pyscript.interpreter.globals.get('L3_VRAM')()
    • the dollar interpolation can only be used within template literals, e.g.,
      `${pyscript.interpreter.globals.get('L3_VRAM')())}`;
      to get the numbers. I used the Number constructor like Number(pyscript.interpreter.globals.get('L3_VRAM')())
    • some python misalignments, most likely due to conversion to text

    The main issue is when the javascript gets executed. The way
    you run it, the javascript code was executed way before the
    pyscript had completed, so it had no data to represent.
    Clearly, the code that builds the chart has to be included
    inside a function (I called it makeChart), and that
    function has to be called when pyscript is ready.

    The approach taken by most examples (examples
    that start a javascript function that uses pyscript
    defined variables), is to call the function as an
    event handler – that is display a button initially
    let the user press it and then display the chart.

    To avoid that, it seems sufficient to just allow
    the code sequence that called the function complete,
    and then, when the event loop takes over, call the
    function that needs to access pyscript global variables.

    For that I defined a javascript function startScript

    function startScript(){
        setTimeout(makeChart, 0); // let the sequence that called startScript complete
    }
    
    <py-script>
        # .............
        
        # at the end of the pyscript
        js.startScript()
    </py-script>
    

    Here’s a full snippet with these and other details:

    function startScript() {
      setTimeout(makeChart, 0); // let the sequence that called startScript complete
    }
    
    function makeChart() {
      var chartDom = document.getElementById('main');
      var myChart = echarts.init(chartDom);
      var option;
      console.log(`In Python right now, x = ${pyscript.interpreter.globals.get('L1_CPU')()}`)
      option = {
        title: {
          text: 'Basic Radar Chart'
        },
        legend: {
          data: ['Laptop 1', 'Laptop 2', 'Laptop 3']
        },
        radar: {
          // shape: 'circle',
          indicator: [{
              name: 'VRAM',
              max: 10
            },
            {
              name: 'RAM',
              max: 10
            },
            {
              name: 'ROM',
              max: 10
            },
            {
              name: 'CPU',
              max: 10
            },
            {
              name: 'Price',
              max: 10
            }
          ]
        },
        series: [{
          name: 'Laptop Specification',
          type: 'radar',
          data: [{
              value: [
                Number(pyscript.interpreter.globals.get('L1_VRAM')()),
                Number(pyscript.interpreter.globals.get('L1_RAM')()),
                Number(pyscript.interpreter.globals.get('L1_ROM')()),
                Number(pyscript.interpreter.globals.get('L1_CPU')()),
                Number(pyscript.interpreter.globals.get('L1_Price')())
              ],
              name: 'Laptop 1'
            },
            {
              value: [
                Number(pyscript.interpreter.globals.get('L2_VRAM')()),
                Number(pyscript.interpreter.globals.get('L2_RAM')()),
                Number(pyscript.interpreter.globals.get('L2_ROM')()),
                Number(pyscript.interpreter.globals.get('L2_CPU')()),
                Number(pyscript.interpreter.globals.get('L2_Price')())
              ],
              name: 'Laptop 2'
            },
            {
              value: [
                Number(pyscript.interpreter.globals.get('L3_VRAM')()),
                Number(pyscript.interpreter.globals.get('L3_RAM')()),
                Number(pyscript.interpreter.globals.get('L3_ROM')()),
                Number(pyscript.interpreter.globals.get('L3_CPU')()),
                Number(pyscript.interpreter.globals.get('L3_Price')())
              ],
              name: 'Laptop 3'
            }
          ]
        }]
      };
    
      option && myChart.setOption(option);
    }
    <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    <script defer src="https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
    <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
    
    <p id="csv"></p>
    
    <py-config type="json">
        {
        "packages": ["pandas"]
        }
    </py-config>
    <py-script>
        import pandas as pd
        import numpy as np
        from pyodide.http import open_url
        #from js import createObject
        #from pyodide.ffi import create_proxy
        #createObject(create_proxy(globals()), "pyodideGlobals")
        url_content = open_url("https://raw.githubusercontent.com/linnlim/Laptop/main/Laptop.csv")
        df = pd.read_csv(url_content)
    
        L1_VRAM = df['VRAM'].loc[df.index[0]]
        L2_VRAM = df['VRAM'].loc[df.index[1]]
        L3_VRAM = df['VRAM'].loc[df.index[2]]
    
        L1_RAM = df['RAM'].loc[df.index[0]]
        L2_RAM = df['RAM'].loc[df.index[1]]
        L3_RAM = df['RAM'].loc[df.index[2]]
    
        L1_ROM = df['ROM'].loc[df.index[0]]
        L2_ROM = df['ROM'].loc[df.index[1]]
        L3_ROM = df['ROM'].loc[df.index[2]]
    
        L1_CPU = df['CPU'].loc[df.index[0]]
        L2_CPU = df['CPU'].loc[df.index[1]]
        L3_CPU = df['CPU'].loc[df.index[2]]
    
        L1_Price = df['Price'].loc[df.index[0]]
        L2_Price = df['Price'].loc[df.index[1]]
        L3_Price = df['Price'].loc[df.index[2]]
    
    
        def L1_VRAM():
            return df['VRAM'].loc[df.index[0]]
        def L2_VRAM():
            return df['VRAM'].loc[df.index[1]]
        def L3_VRAM():
            return df['VRAM'].loc[df.index[2]]
    
        def L1_RAM():
            return df['RAM'].loc[df.index[0]]
        def L2_RAM():
            return df['RAM'].loc[df.index[1]]
        def L3_RAM():
            return df['RAM'].loc[df.index[2]]
    
        def L1_ROM():
            return df['ROM'].loc[df.index[0]]
        def L2_ROM():
            return df['ROM'].loc[df.index[1]]
        def L3_ROM():
            return df['ROM'].loc[df.index[2]]
    
        def L1_CPU():
            return df['CPU'].loc[df.index[0]]
        def L2_CPU():
            return df['CPU'].loc[df.index[1]]
        def L3_CPU():
            return df['CPU'].loc[df.index[2]]
    
        def L1_Price():
            return df['Price'].loc[df.index[0]]
        def L2_Price():
            return df['Price'].loc[df.index[1]]
        def L3_Price():
            return df['Price'].loc[df.index[2]]
    
        csv = Element('csv')
        csv.write(L3_CPU())
    
        js.startScript()
    </py-script>
    <div id="main" style="width: 600px;height:400px;"></div>

    I refrained from optimizing the code in order to keep it as much as possible similar to the original post. While the snippet shows the javascript on top, the original sequence that had the javascript at the end of the file works.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search