Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions for executing MapLibre notebook #806

Merged
merged 3 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions docs/maplibre/add_gif.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[![image](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://demo.leafmap.org/lab/index.html?path=maplibre/add_gif.ipynb)\n",
"[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/leafmap/blob/master/docs/maplibre/add_gif.ipynb)\n",
"[![image](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/opengeos/leafmap/HEAD)\n",
"\n",
"**Add GIF animations to the map**\n",
"\n",
"This example shows how to add GIF animations to the map.\n",
"\n",
"Uncomment the following line to install [leafmap](https://leafmap.org) if needed."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# %pip install \"leafmap[maplibre]\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import leafmap.maplibregl as leafmap"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m = leafmap.Map(center=[-100, 40], zoom=3, style=\"positron\")\n",
"image = \"https://i.imgur.com/KeiAsTv.gif\"\n",
"m.add_image(image=image, width=250, height=250, position=\"bottom-right\")\n",
"text = \"I love sloth!🦥\"\n",
"m.add_text(text, fontsize=35, padding=\"20px\")\n",
"image2 = \"https://i.imgur.com/kZC2tpr.gif\"\n",
"m.add_image(image=image2, bg_color=\"transparent\", position=\"bottom-left\")\n",
"m"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![](https://i.imgur.com/auytBtD.png)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
6 changes: 6 additions & 0 deletions docs/maplibre/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ Add deck.gl layers to the map.

[![](https://i.imgur.com/rQR4687.png)](https://leafmap.org/maplibre/add_deckgl_layer)

## Add GIF animations to the map

Add GIF animations to the map.

[![](https://i.imgur.com/auytBtD.png)](https://leafmap.org/maplibre/add_gif)

## Add HTML content to the map

Add HTML content to the map.
Expand Down
122 changes: 122 additions & 0 deletions leafmap/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13616,7 +13616,9 @@ def execute_notebook_dir(in_dir):
from pathlib import Path

in_dir = os.path.abspath(in_dir)

files = list(Path(in_dir).rglob("*.ipynb"))
files.sort()
count = len(files)
if files is not None:
for index, file in enumerate(files):
Expand All @@ -13625,6 +13627,126 @@ def execute_notebook_dir(in_dir):
execute_notebook(in_file)


def execute_maplibre_notebook_dir(
in_dir: str,
out_dir: str,
delete_html: bool = True,
replace_api_key: bool = True,
recursive: bool = False,
keep_notebook: bool = False,
index_html: bool = True,
) -> None:
"""
Executes Jupyter notebooks found in a specified directory, optionally replacing API keys and deleting HTML outputs.

Args:
in_dir (str): The input directory containing Jupyter notebooks to be executed.
out_dir (str): The output directory where the executed notebooks and their HTML outputs will be saved.
delete_html (bool, optional): If True, deletes any existing HTML files in the output directory before execution. Defaults to True.
replace_api_key (bool, optional): If True, replaces the API key in the output HTML. Defaults to True.
set "MAPTILER_KEY" and "MAPTILER_KEY_PUBLIC" to your MapTiler API key and public key, respectively.
recursive (bool, optional): If True, searches for notebooks in the input directory recursively. Defaults to False.
keep_notebook (bool, optional): If True, keeps the executed notebooks in the output directory. Defaults to False.
index_html (bool, optional): If True, generates an index.html file in the output directory listing all files. Defaults to True.

Returns:
None
"""
import shutil

if not os.path.exists(out_dir):
os.makedirs(out_dir)

if replace_api_key:
os.environ["MAPTILER_REPLACE_KEY"] = "True"

if delete_html:
html_files = find_files(out_dir, "*.html", recursive=recursive)
for file in html_files:
os.remove(file)

files = find_files(in_dir, "*.ipynb", recursive=recursive)
for index, file in enumerate(files):
print(f"Processing {index + 1}/{len(files)}: {file} ...")
basename = os.path.basename(file)
out_file = os.path.join(out_dir, basename)
shutil.copy(file, out_file)

with open(out_file, "r") as f:
lines = f.readlines()

out_lines = []
for line in lines:
if line.strip() == '"m"':
out_lines.append(line.replace("m", "m.to_html()"))
else:
out_lines.append(line)

with open(out_file, "w") as f:
f.writelines(out_lines)

out_html = os.path.basename(out_file).replace(".ipynb", ".html")
os.environ["MAPLIBRE_OUTPUT"] = out_html
execute_notebook(out_file)

if not keep_notebook:
all_files = find_files(out_dir, "*", recursive=recursive)
for file in all_files:
if not file.endswith(".html"):
os.remove(file)

if index_html:
generate_index_html(out_dir)


def generate_index_html(directory: str, output: str = "index.html") -> None:
"""
Generates an HTML file named 'index.html' in the specified directory, listing
all files in that directory as clickable links.

Args:
directory (str): The path to the directory for which to generate the index.html file.
output (str, optional): The name of the output HTML file. Defaults to "index.html".

Returns:
None
"""
# Get a list of files in the directory
files = sorted(
[f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))]
)

# Start the HTML content
html_content = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Index of {directory}</title>
</head>
<body>
<h1>Index of {directory}</h1>
<ul>
""".format(
directory=directory
)

# Add each file to the HTML list
for file in files:
html_content += ' <li><a href="{file}">{file}</a></li>\n'.format(
file=file
)

# Close the HTML content
html_content += """ </ul>
</body>
</html>"""

# Write the HTML content to index.html in the specified directory
with open(os.path.join(directory, output), "w") as f:
f.write(html_content)


def github_get_release_id_by_tag(username, repository, tag_name, access_token=None):
"""
Fetches the release ID by tag name for a given GitHub repository.
Expand Down
34 changes: 30 additions & 4 deletions leafmap/maplibregl.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,10 @@ def show(self) -> None:
def _repr_html_(self, **kwargs):
"""Displays the map."""

filename = os.environ.get("MAPLIBRE_HTML", None)
filename = os.environ.get("MAPLIBRE_OUTPUT", None)
replace_key = os.environ.get("MAPTILER_REPLACE_KEY", False)
if filename is not None:
self.to_html(filename, replace_key=False)
self.to_html(filename, replace_key=replace_key)

def add_layer(
self,
Expand Down Expand Up @@ -1177,6 +1178,7 @@ def to_html(
height: str = "100%",
replace_key: bool = False,
preview: bool = False,
overwrite: bool = False,
**kwargs,
):
"""Render the map to an HTML page.
Expand All @@ -1193,6 +1195,8 @@ def to_html(
The public API key is read from the environment variable `MAPTILER_KEY_PUBLIC`.
Defaults to False.
preview (bool, optional): Whether to preview the HTML file in a web browser.
Defaults to False.
overwrite (bool, optional): Whether to overwrite the output file if it already exists.
**kwargs: Additional keyword arguments that are passed to the
`maplibre.ipywidget.MapWidget.to_html()` method.

Expand Down Expand Up @@ -1226,13 +1230,22 @@ def to_html(
div_before = f"""<div id="pymaplibregl" style="height: {height};"></div>"""
html = html.replace(div_before, div_after)

if replace_key:
if replace_key or (os.getenv("MAPTILER_REPLACE_KEY") is not None):
key_before = get_api_key("MAPTILER_KEY")
key_after = get_api_key("MAPTILER_KEY_PUBLIC")
if key_after is not None:
html = html.replace(key_before, key_after)

output = os.getenv("MAPLIBRE_OUTPUT", None)

if output:

if not overwrite and os.path.exists(output):
import glob

num = len(glob.glob(output.replace(".html", "*.html")))
output = output.replace(".html", f"_{num}.html")

with open(output, "w") as f:
f.write(html)
if preview:
Expand Down Expand Up @@ -1893,8 +1906,21 @@ def add_image(
if id is None:
id = "image"

style = ""
if isinstance(width, int):
style += f"width: {width}px; "
elif isinstance(width, str) and width.endswith("px"):
style += f"width: {width}; "
if isinstance(height, int):
style += f"height: {height}px; "
elif isinstance(height, str) and height.endswith("px"):
style += f"height: {height}; "

if position is not None:
html = f'<img src="{image}">'
if style == "":
html = f'<img src="{image}">'
else:
html = f'<img src="{image}" style="{style}">'
self.add_html(html, position=position, **kwargs)
else:
if isinstance(image, str):
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ nav:
- maplibre/add_colorbar.ipynb
- maplibre/add_components.ipynb
- maplibre/add_deckgl_layer.ipynb
- maplibre/add_gif.ipynb
- maplibre/add_html.ipynb
- maplibre/add_image.ipynb
- maplibre/add_image_generated.ipynb
Expand Down
Loading