for SO https://stackoverflow.com/q/79002984/8508004
Developed in sessions started from here pressing 'launch binder'
.
Go there to get started in with session that this will work in.
# for set-up to save plotly express as static image, based on https://stackoverflow.com/a/59819140/8508004
%pip install kaleido
# for set-up to display pdf in Jupyter cell, based on https://stackoverflow.com/a/19470377/8508004
#%pip install wand # currently not using this; however, leaving as other may have success
# for set-up to display pdf in Jupyter cell, based on https://stackoverflow.com/a/77874408/8508004
%pip install pymupdf
Collecting kaleido Downloading kaleido-0.2.1-py2.py3-none-manylinux1_x86_64.whl.metadata (15 kB) Downloading kaleido-0.2.1-py2.py3-none-manylinux1_x86_64.whl (79.9 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 79.9/79.9 MB 19.2 MB/s eta 0:00:0000:0100:01 Installing collected packages: kaleido Successfully installed kaleido-0.2.1 Note: you may need to restart the kernel to use updated packages. Collecting pymupdf Downloading PyMuPDF-1.24.10-cp310-none-manylinux2014_x86_64.whl.metadata (3.4 kB) Collecting PyMuPDFb==1.24.10 (from pymupdf) Downloading PyMuPDFb-1.24.10-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.4 kB) Downloading PyMuPDF-1.24.10-cp310-none-manylinux2014_x86_64.whl (3.5 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.5/3.5 MB 6.2 MB/s eta 0:00:00a 0:00:01 Downloading PyMuPDFb-1.24.10-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (15.9 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 15.9/15.9 MB 8.5 MB/s eta 0:00:0000:0100:01 Installing collected packages: PyMuPDFb, pymupdf Successfully installed PyMuPDFb-1.24.10 pymupdf-1.24.10 Note: you may need to restart the kernel to use updated packages.
import pandas as pd
import numpy as np
import plotly.io as pio
import plotly.express as px
import plotly.graph_objects as go
np.random.seed(0)
df = pd.DataFrame({'State' : np.repeat(['NY', 'TX', 'FL', 'PA'], 12),
'Month' : np.tile(pd.date_range('2023-09-01', '2024-08-01', freq = 'MS'), 4),
'Actual' : np.random.randint(1000, 1500, size = 48),
'Forecast' : np.random.randint(1000, 1500, size = 48)})
df['Month'] = pd.to_datetime(df['Month'])
df.set_index('Month', inplace = True)
images_made = []
for s in df['State'].unique():
d = df.loc[df['State'] == s, ['Actual', 'Forecast']]
fig = px.line(d, x = d.index, y = d.columns)
fig.update_layout(title = 'Actuals vs Forecast for ' + s, template = 'plotly_dark', xaxis_title = 'Month')
fig.update_xaxes(tickformat = '%Y-%B', dtick = 'M1')
image_filename = "img_file_"+str(s)+".png"
images_made.append(image_filename)
fig.write_image(image_filename)
#fig.show()
'''
# make them into PDF using Pillow according to https://stackoverflow.com/a/63436357/8508004
from PIL import Image
composite_image = Image.open(images_made[0]).convert("RGB") #start what will be composite after rest appended
images_to_append = [Image.open(x).convert("RGB") for x in images_made[1:]]
composite_image.save("composite_of_plots.pdf", save_all=True, append_images=images_to_append)
'''
# make them into single page PDF using Pillow based on https://stackoverflow.com/a/59042517/8508004
from PIL import Image
# get images
#img1 = Image.open('image1.png')
#img2 = Image.open('image2.png')
#img3 = Image.open('image3.png')
#img4 = Image.open('image4.png')
images = [Image.open(x) for x in images_made]
# get width and height
#w1, h1 = img1.size
#w2, h2 = img2.size
#w3, h3 = img3.size
#w4, h4 = img4.size
images_width_height_specs = [(x.size) for x in images]
# to calculate size of new image
#w = max(w1, w2, w3, w4)
#h = max(h1, h2, h3, h4)
w_each = [x[0] for x in images_width_height_specs]
w = max(w_each)
h_each = [x[1] for x in images_width_height_specs]
h = max(h_each)
# create big empty image with place for images
composite_image = Image.new('RGB', (w, h*4))
# put images on new_image
composite_image.paste(images[0], (0, 0))
for idx,x in enumerate(images):
composite_image.paste(x, (0, h*idx))
#new_image.paste(img3, (0, h))
#new_image.paste(img4, (w, h))
# save it
composite_image.save('composite_as_image.png')
images_to_append = [Image.open(x).convert("RGB") for x in images_made[1:]]
#composite_image.save("composite_of_plots.pdf", save_all=True, append_images=images_to_append)
composite_image.save("composite_of_plots.pdf")
ls *.pdf
composite_of_plots.pdf
#DISPLAY OUTPUT PDF IN CELL HERE, based on https://stackoverflow.com/a/19470377/8508004
#from wand.image import Image as WImage
#img = WImage(filename='composite_of_plots.pdf')
#img
# Note that gave me `PolicyError: attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/426` when I tried it in September 2024
# And so I switched to using approach below to Show PDF in Jupyter
#DISPLAY OUTPUT PDF IN CELL HERE, https://stackoverflow.com/a/77874408/8508004
from PIL import Image
import matplotlib.pyplot as plt
import pymupdf
your_path = "composite_of_plots.pdf"
doc = pymupdf.open(your_path)
MAX_PAGES = 1
zoom = 2 # to increase the resolution
mat = pymupdf.Matrix(zoom, zoom)
for i, page in enumerate(doc):
pix = page.get_pixmap(matrix=mat)
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
# display images
plt.figure(figsize=(7,7), facecolor="w")
plt.xticks(color="white")
plt.yticks(color="white")
plt.tick_params(bottom = False)
plt.tick_params(left = False)
plt.imshow(img)
if i > MAX_PAGES - 1:
break