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

Error: HTTP error! status: 404 with Panel #57

Open
MarcSkovMadsen opened this issue Dec 20, 2024 · 4 comments
Open

Error: HTTP error! status: 404 with Panel #57

MarcSkovMadsen opened this issue Dec 20, 2024 · 4 comments

Comments

@MarcSkovMadsen
Copy link

MarcSkovMadsen commented Dec 20, 2024

As the InteractiveFigure has a __repr_html__ I would expect Panel to be able to render it.

But it seems not

image

3e209782-a66b-4ecb-baa9-5cb0d70b580e:18  Uncaught (in promise) Error: HTTP error! status: 404
    at decompressFile (3e209782-a66b-4ecb-baa9-5cb0d70b580e:18:19)
    at async self.onmessage (3e209782-a66b-4ecb-baa9-5cb0d70b580e:28:28)

Reproducible example

import datamapplot
import numpy as np
import pandas as pd
import requests
import bz2
import io
import panel as pn
import numpy as np
import requests
import io

pn.extension(defer_load=True)

base_url = "https://github.com/TutteInstitute/datamapplot"

@pn.cache
def create_plot():
    data_map_file = requests.get(
        f"{base_url}/raw/main/examples/arxiv_ml_data_map.npy"
    )
    arxivml_data_map = np.load(io.BytesIO(data_map_file.content))
    arxivml_label_layers = []
    for layer_num in range(5):
        label_file = requests.get(
            f"{base_url}/raw/interactive/examples/arxiv_ml_layer{layer_num}_cluster_labels.npy"
        )
        arxivml_label_layers.append(np.load(io.BytesIO(label_file.content), allow_pickle=True))
    return datamapplot.create_interactive_plot(
        arxivml_data_map,
        arxivml_label_layers[2],
    )

pn.panel(create_plot()).servable()
 panel serve script.py --dev --index script

I'm running datamapplot==0.4.2, panel==1.5.3 from a terminal on my Jupyterhub.

@MarcSkovMadsen MarcSkovMadsen changed the title How do I get it working with Panel? Error: HTTP error! status: 404 with Panel Dec 20, 2024
@lmcinnes
Copy link
Contributor

The repr_html does some internal mangling to make things work with jupyter (and jupyterhub) that may not work so well outside of that (being served by panel). However, there is just a raw HTML string you can access, and with panel you can just wrap that in an HTML element I would hope. So something like:

import datamapplot
import numpy as np
import pandas as pd
import requests
import bz2
import io
import panel as pn
import numpy as np
import requests
import io

pn.extension(defer_load=True)

base_url = "https://github.com/TutteInstitute/datamapplot"

@pn.cache
def create_plot():
    data_map_file = requests.get(
        f"{base_url}/raw/main/examples/arxiv_ml_data_map.npy"
    )
    arxivml_data_map = np.load(io.BytesIO(data_map_file.content))
    arxivml_label_layers = []
    for layer_num in range(5):
        label_file = requests.get(
            f"{base_url}/raw/interactive/examples/arxiv_ml_layer{layer_num}_cluster_labels.npy"
        )
        arxivml_label_layers.append(np.load(io.BytesIO(label_file.content), allow_pickle=True))
    plot = datamapplot.create_interactive_plot(
        arxivml_data_map,
        arxivml_label_layers[2],
    )
    escaped_html = html.escape(plot._html_str)
    iframe_html = f'<iframe srcdoc="{escaped_html}" style="height:100%; width:100%" frameborder="0"></iframe>'
    return pn.pane.HTML(iframe_html)


pn.panel(create_plot()).servable()

might work better.

@MarcSkovMadsen
Copy link
Author

MarcSkovMadsen commented Dec 22, 2024

Thx. The code above is missing a html import 😉

The code below works

image

import datamapplot
import numpy as np
import pandas as pd
import requests
import bz2
import io
import panel as pn
import numpy as np
import requests
import io
import html
import os
from pathlib import Path
from datamapplot.interactive_rendering import InteractiveFigure


pn.extension(defer_load=True)

base_url = "https://github.com/TutteInstitute/datamapplot"

CACHE = Path(".cache")
CACHE.mkdir(parents=True, exist_ok=True)

DATA_MAP_PLOT_LOGO = "https://github.com/TutteInstitute/datamapplot/raw/main/doc/datamapplot_text_horizontal.png"
DATA_MAP_PLOT_URL = "https://datamapplot.readthedocs.io/en/latest/"

DESCRIPTION = f"""\
Creating **beautiful plots of data maps**.

[**DataMapPlot**]({DATA_MAP_PLOT_URL}) is a small library designed to help you make \
beautiful data map plots for inclusion in presentations, posters and papers.

The focus is on producing static plots, or simple interactive plots, that are great looking \
with as little work for you as possible.\
"""

@pn.cache
def np_load(url, allow_pickle=False):
  filename = os.path.basename(url)
  file = CACHE/filename
  if not file.exists():
    content = requests.get(url).content
    file.write_bytes(content)
  
  return np.load(file, allow_pickle=allow_pickle)

@pn.cache
def create_plot()->InteractiveFigure:
    arxivml_data_map_url = f"{base_url}/raw/main/examples/arxiv_ml_data_map.npy"
    arxivml_data_map = np_load(arxivml_data_map_url)
    arxivml_label_layers = []
    for layer_num in range(5):
        label_url = f"{base_url}/raw/interactive/examples/arxiv_ml_layer{layer_num}_cluster_labels.npy"
        arxivml_label_layers.append(np_load(label_url, allow_pickle=True))
    return datamapplot.create_interactive_plot(
        arxivml_data_map,
        arxivml_label_layers[2],
    )

def to_iframe(plot: InteractiveFigure)->str:
    escaped_html = html.escape(plot._html_str)
    return f'<iframe srcdoc="{escaped_html}" style="height:100%; width:100%;padding:2px;" frameborder="0"></iframe>'

plot = create_plot()
html = to_iframe(plot)

data_map_plot_logo_pane = pn.pane.PNG(DATA_MAP_PLOT_LOGO, link_url=DATA_MAP_PLOT_URL)
plot_pane = pn.pane.HTML(html, sizing_mode="stretch_both", styles={"border": "2px solid var( --neutral-color )", "border-radius": "4px"})

pn.template.FastListTemplate(
  site="Panel",
  title="ArXiv ML Landscape",
  sidebar = [data_map_plot_logo_pane, DESCRIPTION],
  main=[pn.Column("# A data map of papers from the Machine Learning section of ArXiv", plot_pane)],
  main_max_width="1600px",
  main_layout=None,
).servable()

@MarcSkovMadsen
Copy link
Author

MarcSkovMadsen commented Dec 22, 2024

Would it be an idea to provide public to_html and to_iframe methods on the InteractiveFigure to make use cases outside of jupyter easier? Or "fix" _repr_html_? I would expect a _repr_html_ to work in any environment - not just Jupyter.

@lmcinnes
Copy link
Contributor

There is some messiness with jupyter. You can just call str on the plot object and it will give you the html if that's easier.

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

No branches or pull requests

2 participants