Spaces:
Build error
Build error
import streamlit as st | |
import pickle | |
import io | |
from typing import List, Optional | |
import markdown | |
import matplotlib | |
import matplotlib.pyplot as plt | |
import pandas as pd | |
import plotly.graph_objects as go | |
import streamlit as st | |
from plotly import express as px | |
from plotly.subplots import make_subplots | |
from tqdm import trange | |
def load_dataset(data_index): | |
with open(f'./data/preprocessed_image_net/val_data_{data_index}.pkl', 'rb') as file: | |
dataset = pickle.load(file) | |
return dataset | |
def load_dataset_dict(): | |
dataset_dict = {} | |
progress_empty = st.empty() | |
text_empty = st.empty() | |
text_empty.write("Loading datasets...") | |
progress_bar = progress_empty.progress(0.0) | |
for data_index in trange(5): | |
dataset_dict[data_index] = load_dataset(data_index) | |
progress_bar.progress((data_index+1)/5) | |
progress_empty.empty() | |
text_empty.empty() | |
return dataset_dict | |
def make_grid(cols=None,rows=None): | |
grid = [0]*rows | |
for i in range(rows): | |
with st.container(): | |
grid[i] = st.columns(cols) | |
return grid | |
def use_container_width_percentage(percentage_width:int = 75): | |
max_width_str = f"max-width: {percentage_width}%;" | |
st.markdown(f""" | |
<style> | |
.reportview-container .main .block-container{{{max_width_str}}} | |
</style> | |
""", | |
unsafe_allow_html=True, | |
) | |
matplotlib.use("Agg") | |
COLOR = "#31333f" | |
BACKGROUND_COLOR = "#ffffff" | |
def grid_demo(): | |
"""Main function. Run this to run the app""" | |
st.sidebar.title("Layout and Style Experiments") | |
st.sidebar.header("Settings") | |
st.markdown( | |
""" | |
# Layout and Style Experiments | |
The basic question is: Can we create a multi-column dashboard with plots, numbers and text using | |
the [CSS Grid](https://gridbyexample.com/examples)? | |
Can we do it with a nice api? | |
Can have a dark theme? | |
""" | |
) | |
select_block_container_style() | |
add_resources_section() | |
# My preliminary idea of an API for generating a grid | |
with Grid("1 1 1", color=COLOR, background_color=BACKGROUND_COLOR) as grid: | |
grid.cell( | |
class_="a", | |
grid_column_start=2, | |
grid_column_end=3, | |
grid_row_start=1, | |
grid_row_end=2, | |
).markdown("# This is A Markdown Cell") | |
grid.cell("b", 2, 3, 2, 3).text("The cell to the left is a dataframe") | |
grid.cell("c", 3, 4, 2, 3).plotly_chart(get_plotly_fig()) | |
grid.cell("d", 1, 2, 1, 3).dataframe(get_dataframe()) | |
grid.cell("e", 3, 4, 1, 2).markdown( | |
"Try changing the **block container style** in the sidebar!" | |
) | |
grid.cell("f", 1, 3, 3, 4).text( | |
"The cell to the right is a matplotlib svg image" | |
) | |
grid.cell("g", 3, 4, 3, 4).pyplot(get_matplotlib_plt()) | |
def add_resources_section(): | |
"""Adds a resources section to the sidebar""" | |
st.sidebar.header("Add_resources_section") | |
st.sidebar.markdown( | |
""" | |
- [gridbyexample.com] (https://gridbyexample.com/examples/) | |
""" | |
) | |
class Cell: | |
"""A Cell can hold text, markdown, plots etc.""" | |
def __init__( | |
self, | |
class_: str = None, | |
grid_column_start: Optional[int] = None, | |
grid_column_end: Optional[int] = None, | |
grid_row_start: Optional[int] = None, | |
grid_row_end: Optional[int] = None, | |
): | |
self.class_ = class_ | |
self.grid_column_start = grid_column_start | |
self.grid_column_end = grid_column_end | |
self.grid_row_start = grid_row_start | |
self.grid_row_end = grid_row_end | |
self.inner_html = "" | |
def _to_style(self) -> str: | |
return f""" | |
.{self.class_} {{ | |
grid-column-start: {self.grid_column_start}; | |
grid-column-end: {self.grid_column_end}; | |
grid-row-start: {self.grid_row_start}; | |
grid-row-end: {self.grid_row_end}; | |
}} | |
""" | |
def text(self, text: str = ""): | |
self.inner_html = text | |
def markdown(self, text): | |
self.inner_html = markdown.markdown(text) | |
def dataframe(self, dataframe: pd.DataFrame): | |
self.inner_html = dataframe.to_html() | |
def plotly_chart(self, fig): | |
self.inner_html = f""" | |
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script> | |
<body> | |
<p>This should have been a plotly plot. | |
But since *script* tags are removed when inserting MarkDown/ HTML i cannot get it to workto work. | |
But I could potentially save to svg and insert that.</p> | |
<div id='divPlotly'></div> | |
<script> | |
var plotly_data = {fig.to_json()} | |
Plotly.react('divPlotly', plotly_data.data, plotly_data.layout); | |
</script> | |
</body> | |
""" | |
def pyplot(self, fig=None, **kwargs): | |
string_io = io.StringIO() | |
plt.savefig(string_io, format="svg", fig=(2, 2)) | |
svg = string_io.getvalue()[215:] | |
plt.close(fig) | |
self.inner_html = '<div height="200px">' + svg + "</div>" | |
def _to_html(self): | |
return f"""<div class="box {self.class_}">{self.inner_html}</div>""" | |
class Grid: | |
"""A (CSS) Grid""" | |
def __init__( | |
self, | |
template_columns="1 1 1", | |
gap="10px", | |
background_color=COLOR, | |
color=BACKGROUND_COLOR, | |
): | |
self.template_columns = template_columns | |
self.gap = gap | |
self.background_color = background_color | |
self.color = color | |
self.cells: List[Cell] = [] | |
def __enter__(self): | |
return self | |
def __exit__(self, type, value, traceback): | |
st.markdown(self._get_grid_style(), unsafe_allow_html=True) | |
st.markdown(self._get_cells_style(), unsafe_allow_html=True) | |
st.markdown(self._get_cells_html(), unsafe_allow_html=True) | |
def _get_grid_style(self): | |
return f""" | |
<style> | |
.wrapper {{ | |
display: grid; | |
grid-template-columns: {self.template_columns}; | |
grid-gap: {self.gap}; | |
background-color: {self.color}; | |
color: {self.background_color}; | |
}} | |
.box {{ | |
background-color: {self.color}; | |
color: {self.background_color}; | |
border-radius: 0px; | |
padding: 0px; | |
font-size: 100%; | |
text-align: center; | |
}} | |
table {{ | |
color: {self.color} | |
}} | |
</style> | |
""" | |
def _get_cells_style(self): | |
return ( | |
"<style>" | |
+ "\n".join([cell._to_style() for cell in self.cells]) | |
+ "</style>" | |
) | |
def _get_cells_html(self): | |
return ( | |
'<div class="wrapper">' | |
+ "\n".join([cell._to_html() for cell in self.cells]) | |
+ "</div>" | |
) | |
def cell( | |
self, | |
class_: str = None, | |
grid_column_start: Optional[int] = None, | |
grid_column_end: Optional[int] = None, | |
grid_row_start: Optional[int] = None, | |
grid_row_end: Optional[int] = None, | |
): | |
cell = Cell( | |
class_=class_, | |
grid_column_start=grid_column_start, | |
grid_column_end=grid_column_end, | |
grid_row_start=grid_row_start, | |
grid_row_end=grid_row_end, | |
) | |
self.cells.append(cell) | |
return cell | |
def select_block_container_style(): | |
"""Add selection section for setting setting the max-width and padding | |
of the main block container""" | |
st.sidebar.header("Block Container Style") | |
max_width_100_percent = st.sidebar.checkbox("Max-width: 100%?", False) | |
if not max_width_100_percent: | |
max_width = st.sidebar.slider("Select max-width in px", 100, 2000, 1200, 100) | |
else: | |
max_width = 1200 | |
dark_theme = st.sidebar.checkbox("Dark Theme?", False) | |
padding_top = st.sidebar.number_input("Select padding top in rem", 0, 200, 5, 1) | |
padding_right = st.sidebar.number_input("Select padding right in rem", 0, 200, 1, 1) | |
padding_left = st.sidebar.number_input("Select padding left in rem", 0, 200, 1, 1) | |
padding_bottom = st.sidebar.number_input( | |
"Select padding bottom in rem", 0, 200, 10, 1 | |
) | |
if dark_theme: | |
global COLOR | |
global BACKGROUND_COLOR | |
BACKGROUND_COLOR = "rgb(17,17,17)" | |
COLOR = "#fff" | |
_set_block_container_style( | |
max_width, | |
max_width_100_percent, | |
padding_top, | |
padding_right, | |
padding_left, | |
padding_bottom, | |
) | |
def _set_block_container_style( | |
max_width: int = 1200, | |
max_width_100_percent: bool = False, | |
padding_top: int = 5, | |
padding_right: int = 1, | |
padding_left: int = 1, | |
padding_bottom: int = 10, | |
): | |
if max_width_100_percent: | |
max_width_str = f"max-width: 100%;" | |
else: | |
max_width_str = f"max-width: {max_width}px;" | |
st.markdown( | |
f""" | |
<style> | |
.reportview-container .main .block-container{{ | |
{max_width_str} | |
padding-top: {padding_top}rem; | |
padding-right: {padding_right}rem; | |
padding-left: {padding_left}rem; | |
padding-bottom: {padding_bottom}rem; | |
}} | |
.reportview-container .main {{ | |
color: {COLOR}; | |
background-color: {BACKGROUND_COLOR}; | |
}} | |
</style> | |
""", | |
unsafe_allow_html=True, | |
) | |
def get_dataframe() -> pd.DataFrame(): | |
"""Dummy DataFrame""" | |
data = [ | |
{"quantity": 1, "price": 2}, | |
{"quantity": 3, "price": 5}, | |
{"quantity": 4, "price": 8}, | |
] | |
return pd.DataFrame(data) | |
def get_plotly_fig(): | |
"""Dummy Plotly Plot""" | |
return px.line(data_frame=get_dataframe(), x="quantity", y="price") | |
def get_matplotlib_plt(): | |
get_dataframe().plot(kind="line", x="quantity", y="price", figsize=(5, 3)) | |