#!/usr/bin/env python
# coding: utf-8

# for SO https://stackoverflow.com/q/79002984/8508004
# 
# ### 'How to save all plotly express graphs created using a for loop in a pdf' TO SINGLE-PAGE
# 
# Developed in sessions started from [here](https://github.com/fomightez/3Dscatter_plot_mod_playground-binder) pressing `'launch binder'`.  
# Go there to get started in with session that this will work in.

# In[1]:


# for set-up to save plotly express as static image, based on https://stackoverflow.com/a/59819140/8508004
get_ipython().run_line_magic('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
get_ipython().run_line_magic('pip', 'install pymupdf')


# In[2]:


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")


# In[3]:


ls *.pdf


# In[4]:


#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


# In[3]:


#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


# In[ ]: