0

I understand how to create HTML pages with plotly plots. I also understand how to divide these pages in subplots so that I can put several plots in one page.

I would like to put a video or a picture next to a plot.

Is there a way to do this from a python program or should I just edit manually the HTML file product of plotly?

KansaiRobot
  • 7,564
  • 11
  • 71
  • 150

1 Answers1

0
  • concept in comments are https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
  • these can be used for images within figure in plotly (not demonstrated)
  • can be used in HTML (demonstrated by adding additional HTML using BeautifulSoup
  • same approach can be used for videos
  • there is only a need to use data URIs if your images / videos are files hence cannot be distributed as a URL, hence require encoding in HTML using data URIs
import pandas as pd
import plotly.graph_objects as go
import numpy as np
import plotly.express as px
import base64, io, requests
from PIL import Image
from pathlib import Path
import webbrowser
from bs4 import BeautifulSoup


# data for whare images can be found
df_flag = pd.read_csv(
    io.StringIO(
        """country,Alpha-2 code,Alpha-3 code,URL
Australia,AU,AUS,https://www.worldometers.info//img/flags/small/tn_as-flag.gif
New Zealand,NZ,NZL,https://www.worldometers.info//img/flags/small/tn_nz-flag.gif"""
    )
)

# ensure that images exist on your file system...
f = Path.cwd().joinpath("flags")
if not f.exists():
    f.mkdir()

# download some images and use easy to use filenames...
for r in df_flag.iterrows():
    flag_file = f.joinpath(f'{r[1]["Alpha-3 code"]}.gif')
    if not flag_file.exists():
        r = requests.get(r[1]["URL"], stream=True, headers={"User-Agent": "XY"})
        with open(flag_file, "wb") as fd:
            for chunk in r.iter_content(chunk_size=128):
                fd.write(chunk)

# encode
def b64image(country):
    b = io.BytesIO()
    im = Image.open(Path.cwd().joinpath("flags").joinpath(f"{country}.gif"))
    im.save(b, format="PNG")
    b64 = base64.b64encode(b.getvalue())
    return b64.decode("utf-8")


df_flag["image"] = df_flag["Alpha-3 code"].apply(b64image)

# create a figure
fig = px.line(df_flag, x="Alpha-2 code", y=df_flag.index)
fh = Path.cwd().joinpath("html.html")

# add some images to HTML
soup = BeautifulSoup(fig.to_html(include_plotlyjs="cdn", div_id="include image"))
d = soup.body
for i, r in df_flag.iterrows():
    img = soup.new_tag("img", src="data:image/png;base64,"+r["image"])
    d.insert(0, img)

with open(fh, "w") as fp:
    fp.write(str(soup))

# launch it...
webbrowser.open("file://" + str(fh), new=2)

Rob Raymond
  • 29,118
  • 3
  • 14
  • 30