Skip to content

Commit

Permalink
Merge pull request #9 from lsst-dm/tickets/SP-1711
Browse files Browse the repository at this point in the history
SP-1711: Add images endpoint
  • Loading branch information
ctslater authored Nov 12, 2024
2 parents c5985df + 8e532f0 commit b8e550e
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 2 deletions.
23 changes: 21 additions & 2 deletions python/lsst/production/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,38 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from flask import Flask, render_template
import urllib.parse
from werkzeug.routing import BaseConverter

from . import tractTable, logs, bokeh, cache
from . import tractTable, logs, bokeh, cache, images


# This works like the built-in 'path' converter, but
# allows an initial forward slash in the parameter.
class UrlConverter(BaseConverter):

part_isolating = False
regex = ".*?"

def to_python(self, value):
print(value)
return urllib.parse.unquote(value)

def to_url(self, value):
return urllib.parse.quote_plus(value)

def create_app():
app = Flask(
"production-tools",
)
app.url_map.converters['url'] = UrlConverter

app.register_blueprint(logs.bp)
app.register_blueprint(tractTable.bp)
app.register_blueprint(bokeh.bp)
app.register_blueprint(cache.bp)
app.register_blueprint(images.bp)


@app.route("/")
def index():
Expand All @@ -41,4 +60,4 @@ def index():
return app


__all__ = [tractTable, logs, bokeh, create_app, cache]
__all__ = [tractTable, logs, bokeh, create_app, cache, images]
58 changes: 58 additions & 0 deletions python/lsst/production/tools/images.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# This file is part of production-tools.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (https://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.


from flask import Blueprint, send_file, g
import os
import io

from lsst.daf.butler import Butler, DatasetId
from lsst.resources import ResourcePath

bp = Blueprint("images", __name__, url_prefix="/plot-navigator/images", static_folder="../../../../static")

REPO_NAMES = os.getenv("BUTLER_REPO_NAMES").split(",")

def get_butler_map(repo):
if 'butler' not in g:
g.butler_map = {}

if repo in REPO_NAMES and (repo not in g.butler_map.keys()):
g.butler_map[repo] = Butler(repo)

return g.butler_map[repo]

@bp.route("/uuid/<url:repo>/<uuid>")
def index(repo, uuid):

if repo not in REPO_NAMES:
return {"error": f"Invalid repo {repo}"}, 400

butler = get_butler_map(repo)
dataset_ref = butler.get_dataset(DatasetId(uuid))
resource_path = ResourcePath(butler.getURI(dataset_ref))

if dataset_ref.datasetType.storageClass_name != "Plot":
return {"error": "Storage class of dataset is not 'Plot'"}, 400

image = io.BytesIO(resource_path.read())
return send_file(image, mimetype="image/png")

0 comments on commit b8e550e

Please sign in to comment.