holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.69k stars 510 forks source link

Document requirement to serve JSON embed files from HTTP server #1129

Open jshannon-usbr opened 4 years ago

jshannon-usbr commented 4 years ago

ALL software version info

OS: Windows 10 Browser: Chrome Version 80.0.3987.122

Python Environment: python 3.7.6 panel 0.8.0 param 1.9.3 bokeh 1.4.0 numpy 1.18.1 pandas 1.0.1 plotly 4.5.0

Description of expected behavior and the observed behavior

HTML file is generated, but plot is not updating with json data as widgets change.

Complete, minimal, self-contained example code that reproduces the issue

# %% Import libraries.
# Import third party libraries.
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import panel as pn

# %% Define functions.
def random_walk(stdev=0.03):
    """
    Summary
    -------
    Function creating a `pandas` DataFrame of 3 columns, each containing random
    walk data based on provided standard deviation.

    """
    df = pd.DataFrame(np.random.normal(1, 0.03, (100, 3)),
                      columns='JAS BPL AKK'.split())
    df.loc[0] = 1
    df = df.cumprod()
    df *= 40
    return df

def plotly_graph(df):
    """
    Summary
    -------
    Function to create a `plotly` graph with a provided DataFrame.

    """
    fig = go.Figure()
    for c in df.columns:
        trace = go.Scatter(x=df.index, y=df[c].values, mode='lines+markers',
                           name=c)
        fig.add_trace(trace)
    fig.update_layout(hovermode='x')
    return fig

def panel_wrapper(stdev=0.03, dummy_catagory='default'):
    """
    Summary
    -------
    Wrapper function to allow `panel` to redraw `plotly` graphs based on web
    visualization parameter inputs.

    """
    return plotly_graph(random_walk(stdev=stdev))

def main(method_num):
    # Method 1: Quickly create a web visualization with Python back-end
    #           support.
    if method_num == 1:
        # NOTE: Documentation states, "Initializes the pyviz notebook extension
        #       to allow plotting with bokeh and enable comms." It seems that
        #       `panel.extension` is not required when generating web
        #        visualizations with the `.show()` method.
        pn.extension()
        pn.interact(panel_wrapper).show()
    # Method 2: Adjust the layout of the quick creation in Method 1.
    if method_num == 2:
       i = pn.interact(panel_wrapper)
       text = "<br>\n# Random Walk as a Function of Standard Deviation"
       p = pn.Row(i[1][0], pn.Column(text, i[0][0]))
       p.show()
    # Method 3, 4, & 5: Explicitly build the panel objects.
    if method_num == 3 or method_num == 4 or method_num == 5:
        c_opts = ['default', 'optimized', 'calibrated', 'variable']
        dummy_catagory = pn.widgets.RadioButtonGroup(name='dummy_catagory',
                                                     value='default',
                                                     options=c_opts)
        stdev = pn.widgets.FloatSlider(name='stdev', value=0.03, start=0,
                                       end=0.1, step=0.01)
        @pn.depends(stdev, dummy_catagory)
        def reactive_panel(stdev, dummy_catagory):
            return panel_wrapper(stdev, dummy_catagory)
        text = "<br>\n# Random Walk as a Function of Standard Deviation"
        widgets = pn.Column(text, stdev, dummy_catagory)
        p_rw = pn.Row(reactive_panel, widgets)
    # Method 3: Deploy a web visualization with a Python server.
    if method_num == 3:
        p_rw.show()
    # Method 4: Deploy a web visualization with data embedded in HTML.
    # NOTE: This stand alone version works with the following web browsers:
    #           - Chrome Version 80.0.3987.122
    #           - Microsoft Edge 41.16299.1480.0
    #       This stand alone version does not work with the following web
    #       browsers:
    #           - Internet Explorer Version 11.1685.16299.0.
    if method_num == 4:
        f_out = 'test.html'
        p_rw.save(f_out, title='This is a test', embed=True, max_opts=10)
    # Method 5: Deploy a web visualization referencing json data files.
    if method_num == 5:
        f_out = 'test_json.html'
        p_rw.save(f_out, title='This is a test', embed=True, max_opts=10,
                  embed_json=True)
    return 0

# %% Execute script.
if __name__ == '__main__':
    # Select input 1 - 5. See source code notes in main() for more info.
    _ = main(5)

Stack traceback and/or browser JavaScript console output

There is no Python error traceback. I have no experience with JavaScript, so I do not know how to report JavaScript console output.

Screenshots or screencasts of the bug in action

I am unable to provide a screencast of the bug.

Additional Notes

The script above is a tutorial I am providing to my coworkers days before I am resigning. I will be keeping in touch with them as I transition into my new position, and I will be using this tutorial as the basis for new tool development related to water resources modeling. I will be adding the link to this issue in the tutorial so colleagues can stay up to date on this progress. I may respond to your comments/questions from a different GitHub account.

FYI, switching the last line of code from " = main(5)" to " = main(4)" will produce a stand alone HTML web visualization with the data embedded into the source code, and the widgets behave as intended in this case.

MarcSkovMadsen commented 4 years ago

Hi @jshannon-usbr

I will try to take a look. I've never tried embedding before though.

For the screencast you could consider using ScreenToGif. It's free, easy to use and produces high quality .gif videos as output. I use it all the time. A picture is worth a thousand words and a video even more. At least sometimes :-)

MarcSkovMadsen commented 4 years ago

FYI. @Jacob-Barhak

Here is a fellow user of Panels embed functionality and you are one of the experts. If you have time I think it would be very appreciated if you took a look.

Thanks.

MarcSkovMadsen commented 4 years ago

If I run

python 'scripts\issues\issue_jshannon.py'

with the setting main(5)

I see a lot of json files generated as well as a test_json.html file.

image

But it's not interactive.

shannon_main_5

MarcSkovMadsen commented 4 years ago

If I change to main(3) the app displays and is interactive

shannon_main_6

MarcSkovMadsen commented 4 years ago

I tried opening the browser debugging console via CTR+SHIFT+I on windows and in Firefox for the main(5) version and I can actually see that an error is logged everytime I move the slider.

image

MarcSkovMadsen commented 4 years ago

I clicked the learn more and I see

image

So I belive that the problem is that in newer browsers you no longer can load local file resources.

I believe the static files generated would work if served from an url. For example by saving them to a GitHub account.

FYI. @philippjfr

MarcSkovMadsen commented 4 years ago

It's the same problem in Chrome if I use CTRL+SHIFT+I

image

Jacob-Barhak commented 4 years ago

Hi @MarcSkovMadsen , Hi @jshannon-usbr

Not sure about this problem specifically, yet when it works fine in Edge browser under windows, yet breaks under chrome for some reason. Also, I know there are some other issues with embed at the html level. Here is another that is known to be a bug: https://github.com/holoviz/panel/issues/1083

This seems to be something that either the Bokeh group of the panel developers need to resolve. However, you are using plotly which is new to me. So this may contribute to the problem - really not sure here - the panel experts will have to answer this.

However, if you are using windows, it works nice to edge , so you have a working solution. Did not try it on other browsers, perhaps there are other working solutions.

I hope it helps.

philippjfr commented 4 years ago

If you are exporting to JSON files then those need to be served by an HTTP server otherwise you will get these CORS issues. Try starting a python -m http.server and view the file. So I think this simply needs to be documented better but there is nothing we can get around the security policy of different browsers.

jshannon415 commented 4 years ago

Hi @MarcSkovMadsen @Jacob-Barhak @philippjfr This is @jshannon-usbr responding from my personal account. Thanks so much for the quick responses! This is one of my first issue submissions on GitHub, and you all have made the collaborative experience a positive one. I am satisfied knowing the limitations of this workflow in order to move forward in my own applications, so I will leave it to you if you think this issue should remain open or closed.

@MarcSkovMadsen Thanks you for taking the time to look into this issue and providing more clarity on the problem. I will take your advice and include ScreenToGif to my collaboration toolset.

@Jacob-Barhak Thanks for noting the 'testjson.html' produced in ` = main(5)` works with Microsoft Edge. I was able to confirm this too and will take note of this limitation as I craft visualization products in my new position. I believe Microsoft Edge will be the default web browser in my new position, so this may be the best solution as web visualizations become more complex. I was just made aware too that some higher level managers use iPads to view data in meetings, so I will have to perform some tests in Safari, but it will be at least a month before I expect to follow up with results. I do not expect any major issues once the webpage is hosted.

@philippjfr Thanks for making me aware of Python's http.server library. For future civil engineers like myself who stumble upon this issue, here are instructions for running 'test_json.html' on a Python HTTP server (based on a tutorial I found here):

  1. Change console working directory to location containing 'test_json.html';
  2. Execute python -m http.server in console;
  3. Open your preferred web browser and type in the address bar 'localhost:port_num', where port_num is the port number returned from the console after activating the Python HTTP server (e.g. if the returned port number is 8080, type 'localhost:8080').
  4. Your web browser should show a directory listing that includes 'test_json.html'; click on the link to view the web visualization.