Skip to content

Commit ed09a1e

Browse files
authored
Fix: Optimize PNGs by reducing filesize (#13)
* optimize pngs * move entrypoint * fix mypy * .
1 parent caeffd9 commit ed09a1e

File tree

5 files changed

+44
-5
lines changed

5 files changed

+44
-5
lines changed

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
3939
- name: Build site
4040
run: |
41-
uv run main.py
41+
uv run -m wavey --resolution f
4242
env:
4343
TQDM_DISABLE: 1
4444

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ dependencies = [
1212
"matplotlib",
1313
"mpld3",
1414
"numpy",
15+
"pillow>=9.1",
1516
"pygrib",
1617
"requests",
1718
"tqdm",

uv.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

main.py renamed to wavey/__main__.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import datetime
2+
import io
23
import logging
34
from pathlib import Path
45

56
import matplotlib
67
import matplotlib.pyplot as plt
78
import mpld3
89
import numpy as np
10+
import PIL.Image
911
import pygrib
1012
from jinja2 import Environment, PackageLoader, select_autoescape
1113
from tqdm import tqdm
1214

1315
from wavey.common import DATETIME_FORMAT, FEET_PER_METER, TZ_PACIFIC, TZ_UTC, setup_logging
1416
from wavey.grib import NUM_DATA_POINTS, ForecastType, read_forecast_data
15-
from wavey.map import DEFAULT_ARROW_LENGTH, Map
17+
from wavey.map import DEFAULT_ARROW_LENGTH, RESOLUTION, Map
1618
from wavey.nwfs import download_forecast, get_most_recent_forecast
1719

1820
# Force non-interactive backend to keep consistency between local and github actions
@@ -43,10 +45,30 @@ def utc_to_pt(dt: datetime.datetime) -> datetime.datetime:
4345
return dt.astimezone(tz=TZ_PACIFIC)
4446

4547

48+
def savefig(path: Path) -> None:
49+
"""
50+
Save matplotlib figure to PNG file.
51+
52+
We perform a bit of optimization to make the output filesize smaller
53+
without sacrificing quality.
54+
55+
Args:
56+
path: Path to output PNG file.
57+
"""
58+
59+
bts = io.BytesIO()
60+
plt.savefig(bts, format="png")
61+
62+
with PIL.Image.open(bts) as img:
63+
img2 = img.convert("RGB").convert("P", palette=PIL.Image.Palette.ADAPTIVE)
64+
img2.save(path, format="png")
65+
66+
4667
def main(
4768
grib_path: Path | None = None,
4869
/,
4970
out_dir: Path = Path("_site"),
71+
resolution: RESOLUTION = "h",
5072
) -> None:
5173
"""
5274
Create plots for significant wave height.
@@ -56,8 +78,13 @@ def main(
5678
https://nomads.ncep.noaa.gov/pub/data/nccf/com/nwps/prod/. If none,
5779
will download the most recent one to the current directory.
5880
out_dir: Path to output directory.
81+
resolution: Resolution of the coastline map. Options are crude, low,
82+
intermediate, high, and full.
5983
"""
6084

85+
if resolution != "f":
86+
LOG.warning("Not drawing full resolution coastlines. Use the flag '--resolution f'")
87+
6188
out_dir.mkdir(parents=True, exist_ok=True)
6289

6390
# Download data, if needed
@@ -126,6 +153,7 @@ def main(
126153
lat_max_idx=110,
127154
lon_min_idx=20,
128155
lon_max_idx=70,
156+
resolution=resolution,
129157
)
130158

131159
LOG.info("Drawing Breakwater map")
@@ -140,6 +168,7 @@ def main(
140168
lat_max_idx=BREAKWATER_LAT_IDX + 3,
141169
lon_min_idx=BREAKWATER_LON_IDX - 2,
142170
lon_max_idx=BREAKWATER_LON_IDX + 3,
171+
resolution=resolution,
143172
draw_arrows_length=DEFAULT_ARROW_LENGTH / 3,
144173
draw_arrows_stride=1,
145174
)
@@ -157,6 +186,7 @@ def main(
157186
lat_max_idx=MONASTERY_LAT_IDX + 4,
158187
lon_min_idx=MONASTERY_LON_IDX - 3,
159188
lon_max_idx=MONASTERY_LON_IDX + 2,
189+
resolution=resolution,
160190
draw_arrows_length=DEFAULT_ARROW_LENGTH / 3,
161191
draw_arrows_stride=1,
162192
)
@@ -176,7 +206,7 @@ def main(
176206
map_mon.update(hour_i)
177207

178208
ax_main.set_title(f"Significant wave height (ft) and wave direction\nHour {hour_i:03} -- {pacific_time_str}")
179-
plt.savefig(plot_dir / f"{hour_i}.png")
209+
savefig(plot_dir / f"{hour_i}.png")
180210

181211
# Get current time
182212

wavey/map.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Iterable, NamedTuple
2+
from typing import Iterable, Literal, NamedTuple
33

44
import matplotlib
55
import matplotlib.colors as mcolors
@@ -125,6 +125,9 @@ def _update_arrows(
125125
arrow.arrow.set_data(x=arrow_start[0], y=arrow_start[1], dx=dir_vec[0], dy=dir_vec[1])
126126

127127

128+
RESOLUTION = Literal["c", "l", "i", "h", "f"]
129+
130+
128131
class Map:
129132
def __init__(
130133
self,
@@ -137,6 +140,7 @@ def __init__(
137140
lat_max_idx: int,
138141
lon_min_idx: int,
139142
lon_max_idx: int,
143+
resolution: RESOLUTION = "h",
140144
draw_arrows_length: float = DEFAULT_ARROW_LENGTH,
141145
draw_arrows_stride: int = 3,
142146
) -> None:
@@ -156,6 +160,8 @@ def __init__(
156160
lat_max_idx: For zooming-in to a smaller lat/lon bounding box.
157161
lon_min_idx: For zooming-in to a smaller lat/lon bounding box.
158162
lon_max_idx: For zooming-in to a smaller lat/lon bounding box.
163+
resolution: Resolution of the coastline map. Options are crude,
164+
low, intermediate, high, and full.
159165
draw_arrows_length: Length of arrows.
160166
draw_arrows_stride: Create an arrow for every multiple of `stride`
161167
indicies.
@@ -187,7 +193,7 @@ def __init__(
187193
llcrnrlon=lon_min,
188194
urcrnrlat=lat_max,
189195
urcrnrlon=lon_max,
190-
resolution="f",
196+
resolution=resolution,
191197
ax=ax,
192198
)
193199
map.drawcoastlines()

0 commit comments

Comments
 (0)