Arrange thumbnails as a gallery
#|default_exp gallery
#|export
from nb_thumb.thumb import nb2thumb
from pathlib import Path
from fastcore.foundation import L
from fastcore.utils import mkdir
from fastcore.test import test_eq
#|export
def emb_img(nb_path:str, # the path to the notebook
label:str, # the label indicating the cell where the plot is, see https://quarto.org/docs/authoring/notebook-embed.html#code-cell-options for an example.
caption:str='', # the caption, will be inferred from label if not specified.
anchor='#example', # anchor tag in source page, this defaults to `#example` for plotnine: https://plotnine.readthedocs.io
size=(150,150) # size of the thumbnail
) -> str:
"Embed a thumbnail image as a markdown cell."
if not caption: caption = label.replace('_', ' ').title()
d = mkdir(f'gallery_plot_data/{Path(nb_path).stem}', exist_ok=True, parents=True)
img = nb2thumb(nb_path, label=label, size=size)
outfile = d/f'{label}.png'
img.save(outfile)
return f"""
::: {{.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}}
{{.plot-gallery}}
[{caption}]({nb_path}{anchor})
:::
"""
We can embed an image with markdown like this:
#|output: asis
md = emb_img(nb_path='test_nbs/geom_col.ipynb',
label='two_variable_bar_plot')
print(md)
::: {.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}
{.plot-gallery}
[Two Variable Bar Plot](test_nbs/geom_col.ipynb#example)
:::
#|hide
test_eq(md, """
::: {.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}
{.plot-gallery}
[Two Variable Bar Plot](test_nbs/geom_col.ipynb#example)
:::
""")
#|export
def gallery(plots:list[dict] # a list of dictionaries which contain arguments for `emb_img`.
) -> str:
"Arrange plots into a gallery."
md = L(plots).map(lambda x: emb_img(**x))
return '\n::: {.content-block .grid .gap-4}\n' + '\n'.join(md) + '\n:::'
To use gallery, you must construct a list of dicts whose keys are arguments to emb_img:
plots = \
[
dict(nb_path= 'test_nbs/geom_col.ipynb',
label='two_variable_bar_plot'),
dict(nb_path='test_nbs/PlotnineAnimation.ipynb',
label='spiral'),
dict(nb_path='test_nbs/geom_density.ipynb',
label='density_curve'),
dict(nb_path='test_nbs/geom_map.ipynb',
label='map'),
dict(nb_path='test_nbs/geom_segment.ipynb',
label='ranges'),
dict(nb_path='test_nbs/geom_segment.ipynb',
label='rank')
]
:::{.callout-important}
For this gallery to show up well in Quarto, we recommend including the following css in your quarto project:
/* css styles */
.plot-gallery {
height: 175px;
object-fit: contain;
}
Note that the class plot-gallery is inserted by gallery around each image.
:::
#|output:asis
print(gallery(plots))
::: {.content-block .grid .gap-4}
::: {.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}
{.plot-gallery}
[Two Variable Bar Plot](test_nbs/geom_col.ipynb#example)
:::
::: {.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}
{.plot-gallery}
[Spiral](test_nbs/PlotnineAnimation.ipynb#example)
:::
::: {.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}
{.plot-gallery}
[Density Curve](test_nbs/geom_density.ipynb#example)
:::
::: {.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}
{.plot-gallery}
[Map](test_nbs/geom_map.ipynb#example)
:::
::: {.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}
{.plot-gallery}
[Ranges](test_nbs/geom_segment.ipynb#example)
:::
::: {.g-col-6 .g-col-md-6 .mb-4 .border .rounded .shadow-sm .d-flex .flex-column .justify-content-center .align-items-center .px-3}
{.plot-gallery}
[Rank](test_nbs/geom_segment.ipynb#example)
:::
:::