commit abcf58eaa84bb49c4a8be269e7435a62606a9888
parent 897dc2fb4dcc80db65ef52a2b88b23f242f32031
Author: david cochran <about.trout@gmail.com>
Date: Tue, 1 Apr 2025 20:06:34 -0700
remove gallery
i stopped updating it
Diffstat:
5 files changed, 2 insertions(+), 258 deletions(-)
diff --git a/README.md b/README.md
@@ -2,10 +2,6 @@ _Pillar Point boats, birds, [~~and waves~~](https://github.com/abtrout/ppbbww/is
[`ppbw`](/ppboatwatch/ppbw.py) is a Python project that samples frames from the [Mavericks](https://en.wikipedia.org/wiki/Mavericks,_California) Surfline cam and runs [facebook/detr-resnet-50](https://huggingface.co/facebook/detr-resnet-50) on them to detect various objects, e.g. boats and birds. Matches are archived in a SQLite database and announced to a shared Slack channel to be enjoyed with friends.
-After running this for a while, _many neat images_ were captured, which lead to the creation of the gallery. There's a small [`curator`](/ppboatwatch/gallery.py#L77-L80) web app for hand picking gallery-worthy images from the matches database, and a script to [`generate`](/ppboatwatch/gallery.py#L83-L114) a static Jekyll site that's suitable to be deployed on my [`gh-pages`](https://github.com/abtrout/ppbbww/tree/gh-pages) branch. I curate by hand and manually push updates sometimes, ¯\\\_(ツ)_/¯.
-
-__[Check out the gallery here!](https://abtrout.github.io/ppbbww)__
-
#### Getting started
```
diff --git a/ppboatwatch/archive.py b/ppboatwatch/archive.py
@@ -10,8 +10,7 @@ CREATE TABLE IF NOT EXISTS matches (
filename,
label,
score,
- x0, y0, x1, y1,
- gallery DEFAULT NULL
+ x0, y0, x1, y1
)"""
ADD_MATCH_SQL = """
@@ -19,24 +18,9 @@ INSERT INTO matches (ts, filename, label, score, x0, y0, x1, y1)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"""
LIST_MATCHES_SQL = """
-SELECT ts, filename, label, score, x0, y0, x1, y1, gallery
+SELECT ts, filename, label, score, x0, y0, x1, y1
FROM matches ORDER BY ts DESC"""
-LIST_GALLERY_MATCHES_SQL = """
-SELECT ts, filename, label, score, x0, y0, x1, y1, gallery
-FROM matches WHERE gallery IS NOT NULL ORDER BY ts DESC"""
-
-UPDATE_GALLERY_SQL = """
-UPDATE matches SET gallery = ? WHERE ts = ?"""
-
-GET_MATCH_PAGE_SQL = """
-SELECT ts, filename, label, score, x0, y0, x1, y1, gallery, previous_ts, next_ts
-FROM (SELECT *,
- LAG(ts, 1) OVER (ORDER BY ts DESC) AS next_ts,
- LEAD(ts, 1) OVER (ORDER BY ts DESC) AS previous_ts
- FROM matches ORDER BY ts DESC
-) WHERE ts = ?"""
-
class Archive:
def __init__(self, db_file):
@@ -55,22 +39,3 @@ class Archive:
with closing(self.con.cursor()) as cur:
return cur.execute(LIST_MATCHES_SQL).fetchall()
- def list_gallery_matches(self):
- with closing(self.con.cursor()) as cur:
- return cur.execute(LIST_GALLERY_MATCHES_SQL).fetchall()
-
- def get_match_page(self, ts):
- with closing(self.con.cursor()) as cur:
- return cur.execute(GET_MATCH_PAGE_SQL, (ts,)).fetchone()
-
- def set_gallery(self, ts):
- return self.__update_gallery(ts, 1)
-
- def unset_gallery(self, ts):
- return self.__update_gallery(ts, None)
-
- def __update_gallery(self, ts, value):
- with closing(self.con.cursor()) as cur:
- res = cur.execute(UPDATE_GALLERY_SQL, (value, ts))
- self.con.commit()
- return res
diff --git a/ppboatwatch/gallery.html b/ppboatwatch/gallery.html
@@ -1,101 +0,0 @@
-<!doctype html>
-<html>
- <head>
- <title>Ppbbww | {{ date_time }}</title>
- <style type="text/css">
- * {
- padding: 0;
- margin: 0;
- }
- .container {
- width: 90%;
- max-width: 800px;
- margin: 5em auto;
- font-family: monospace;
- font-size: 1.5em;
- color: #626262;
- }
- .column {
- float: left;
- width: 33.3%;
- }
- .row { margin: 10px 0; }
- .row:after {
- content: "";
- display: table;
- clear: both;
- }
- a {
- font-weight: bold;
- text-decoration: none;
- color: #626262;
- }
- .text-left { text-align: left; }
- .text-right { text-align: right; }
- .text-center { text-align: center; }
- .title {
- font-size: 2em;
- text-decoration: none;
- color: #626262;
- }
- .button-red, .button-green {
- border: 0;
- border-radius: 0.75em;
- padding: 0.5em 1em;
- margin: 1em 0;
- font-family: monospace;
- font-size: 1em;
- color: #f2f2f2;
- }
- .button-green { background-color: green; }
- .button-red { background-color: red; }
- </style>
- </head>
- <body>
- <div class="container">
- <div class="row">
- <a href="/" class="title">Ppbbww</a>
- </div>
- <img src="/{{ filename }}" width=100% height=auto>
- <div class="row">
- <div class="column text-left">
- {% if prev_ts %}
- <a href="/gallery/{{ prev_ts }}">Older posts</a>
- {% endif %}
-
- </div>
- <div class="column text-center">
- {{ date_time }}
- </div>
- <div class="column text-right">
-
- {% if next_ts %}
- <a href="/gallery/{{ next_ts }}">Newer posts</a>
- {% endif %}
- <div></div>
- </div>
- <div class="row text-center">
- {% if gallery %}
- <button type="button" class="button-red" onClick="unsetGallery({{ ts }})">Remove from Gallery</button>
- {% else %}
- <button type="button" class="button-green" onClick="setGallery({{ ts }})">Add to Gallery</button>
- {% endif %}
- </div>
- </div>
- </div>
- <script type="text/javascript">
- function setGallery(ts) {
- const req = new XMLHttpRequest();
- req.open("PUT", `/gallery/${ts}`)
- req.onreadystatechange = function() { location.reload() }
- req.send()
- }
- function unsetGallery(ts) {
- const req = new XMLHttpRequest();
- req.open("DELETE", `/gallery/${ts}`)
- req.onreadystatechange = function() { location.reload() }
- req.send()
- }
- </script>
- </body>
-</html>
diff --git a/ppboatwatch/gallery.py b/ppboatwatch/gallery.py
@@ -1,114 +0,0 @@
-import aiohttp_jinja2
-import jinja2
-import os
-import shutil
-import sys
-
-from aiohttp import web
-from datetime import datetime
-from itertools import groupby
-
-from .archive import Archive
-
-
-class Curator:
- def __init__(self, db_file):
- self.archive = Archive(db_file)
- self.app = web.Application()
- self.app.add_routes(
- [
- web.get("/", self.redirect_latest),
- web.get("/gallery/{ts}", self.display_match),
- web.put("/gallery/{ts}", self.set_gallery),
- web.delete("/gallery/{ts}", self.unset_gallery),
- web.static("/data", "./data"),
- ]
- )
- aiohttp_jinja2.setup(self.app, loader=jinja2.FileSystemLoader("./ppboatwatch/"))
-
- def run(self):
- web.run_app(self.app)
-
- async def redirect_latest(self, request):
- ts, _, _, _, _, _, _, _, _ = self.archive.list_matches()[0]
- raise web.HTTPFound(f"/gallery/{ts}")
-
- async def display_match(self, request):
- ts = int(request.match_info["ts"])
- (ts, filename, label, score, x0, y0, x1, y1, gallery, previous_ts, next_ts) = (
- self.archive.get_match_page(ts)
- )
- dt = datetime.fromtimestamp(int(ts)).strftime("%Y-%m-%d %I:%M:%S")
- context = {
- "date_time": dt,
- "prev_ts": previous_ts,
- "ts": ts,
- "next_ts": next_ts,
- "filename": filename,
- "label": label,
- "score": score,
- "x0": x0,
- "y0": y0,
- "x1": x1,
- "y1": y1,
- "gallery": True if gallery else False,
- }
- return aiohttp_jinja2.render_template("gallery.html", request, context)
-
- async def set_gallery(self, request):
- ts = request.match_info["ts"]
- try:
- self.archive.set_gallery(int(ts))
- return web.Response(status=200)
- except Exception as ex:
- logging.error(f"Failed to set_gallery: {ex}")
- return web.Response(status=500)
-
- async def unset_gallery(self, request):
- ts = request.match_info["ts"]
- try:
- self.archive.unset_gallery(int(ts))
- return web.Response(status=200)
- except Exception as ex:
- logging.error(f"Failed to set_gallery: {ex}")
- return web.Response(status=500)
-
-
-# Entry point for gallery curation web UI.
-def curate():
- curator = Curator("archive.db")
- curator.run()
-
-
-# Entry point for static gallery generation; produces _layouts and
-# assets/img folders for jekyll gh-pages site, based on the `gallery`
-# column in an Archive.
-def generate():
- if not os.path.exists("gallery"):
- os.makedirs("gallery")
- if not os.path.exists("_posts"):
- os.makedirs("_posts")
-
- rows = Archive("archive.db").list_gallery_matches()
- all_matches = list(groupby(rows, key=lambda cols: (cols[0], cols[1])))
- for i, ((ts, f), matches) in enumerate(all_matches):
- # Copy frame file to gallery.
- shutil.copyfile(f, f"gallery/{ts}.jpg")
- # Make a new post.
- ymd = datetime.fromtimestamp(int(ts)).strftime("%Y-%m-%d")
- with open(f"_posts/{ymd}-{ts}.md", "w") as post_file:
- dt = datetime.fromtimestamp(int(ts)).strftime("%Y-%m-%d %I:%M:%S")
- # TODO: Could add lag/lead to LIST_GALLERY_MATCHES_SQL query instead.
- next_ts = all_matches[i - 1][0][0] if i > 0 else None
- prev_ts = all_matches[i + 1][0][0] if i < len(all_matches) - 1 else None
- post_file.writelines(
- [
- "---\n",
- "layout: default\n",
- f"ts: {ts}\n",
- f"prev_ts: {prev_ts}\n" if prev_ts else "",
- f"next_ts: {next_ts}\n" if next_ts else "",
- f'date_time: "{dt}"\n',
- "---\n",
- ]
- )
diff --git a/pyproject.toml b/pyproject.toml
@@ -53,9 +53,7 @@ dependencies = [
]
[project.scripts]
-curate-gallery = "ppboatwatch.gallery:curate"
find-objects = "ppboatwatch.find_objects:main"
-gen-gallery = "ppboatwatch.gallery:generate"
ppbbww = "ppboatwatch.ppbbww:main"
sample-streams = "ppboatwatch.sample_streams:main"