288 lines
8.5 KiB
Python
288 lines
8.5 KiB
Python
# Copyright (2019-2022) Paul Scherrer Institute
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from io import BytesIO
|
|
|
|
import grpc
|
|
import numpy
|
|
from fastapi import FastAPI, Body, HTTPException, Response
|
|
from fastapi.responses import RedirectResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
from google.protobuf.json_format import Parse, ParseError, MessageToDict
|
|
from tifffile import imwrite
|
|
|
|
import jfjoch_pb2
|
|
import jfjoch_pb2_grpc
|
|
|
|
static_directory = "/home/leonarski_f/nextgendcu/frontend_ui/build"
|
|
grpc_addr = "localhost:5232"
|
|
|
|
app = FastAPI()
|
|
|
|
app.mount("/frontend", StaticFiles(directory=static_directory), name="static")
|
|
|
|
MAX_MESSAGE_LENGTH = 64 * 1024 * 1024
|
|
channel = grpc.insecure_channel(
|
|
grpc_addr,
|
|
options=[
|
|
("grpc.max_send_message_length", MAX_MESSAGE_LENGTH),
|
|
("grpc.max_receive_message_length", MAX_MESSAGE_LENGTH),
|
|
],
|
|
)
|
|
stub = jfjoch_pb2_grpc.gRPC_JFJochBrokerStub(channel)
|
|
|
|
|
|
@app.get("/", response_class=RedirectResponse)
|
|
async def get_root():
|
|
return "/frontend/index.html"
|
|
|
|
|
|
@app.get("/frontend", response_class=RedirectResponse)
|
|
async def get_frontend():
|
|
return "/frontend/index.html"
|
|
|
|
|
|
@app.post("/detector/pedestal")
|
|
async def pedestal():
|
|
try:
|
|
stub.Pedestal(jfjoch_pb2.Empty())
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
return {}
|
|
|
|
|
|
@app.post("/detector/initialize")
|
|
async def initialize():
|
|
try:
|
|
stub.Initialize(jfjoch_pb2.Empty())
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
return {}
|
|
|
|
|
|
@app.post("/detector/deactivate")
|
|
async def deactivate():
|
|
try:
|
|
stub.Deactivate(jfjoch_pb2.Empty())
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
return {}
|
|
|
|
|
|
@app.post("/detector/start")
|
|
async def start(data: str = Body(...)):
|
|
try:
|
|
stub.Start(Parse(data, jfjoch_pb2.DatasetSettings()))
|
|
return {}
|
|
except ParseError as e:
|
|
return HTTPException(status_code=400, detail="Parser error: " + str(e))
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.post("/detector/stop")
|
|
async def stop():
|
|
try:
|
|
stub.Stop(jfjoch_pb2.Empty())
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
return {}
|
|
|
|
|
|
@app.post("/detector/trigger")
|
|
async def stop():
|
|
try:
|
|
stub.Trigger(jfjoch_pb2.Empty())
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
return {}
|
|
|
|
|
|
@app.get("/detector/status")
|
|
async def get_status():
|
|
try:
|
|
return MessageToDict(
|
|
stub.GetStatus(jfjoch_pb2.Empty()), including_default_value_fields=True
|
|
)
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.get("/detector/settings")
|
|
async def get_settings():
|
|
try:
|
|
return MessageToDict(
|
|
stub.GetDetectorSettings(jfjoch_pb2.Empty()),
|
|
including_default_value_fields=True,
|
|
)
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.put("/detector/settings")
|
|
async def put_settings(data: str = Body(...)):
|
|
try:
|
|
stub.PutDetectorSettings(Parse(data, jfjoch_pb2.DetectorSettings()))
|
|
return {}
|
|
except ParseError as e:
|
|
return HTTPException(status_code=400, detail="Parser error: " + str(e))
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.get("/detector/calibration")
|
|
async def get_calibration():
|
|
try:
|
|
return MessageToDict(
|
|
stub.GetCalibrationStatistics(jfjoch_pb2.Empty()),
|
|
including_default_value_fields=True,
|
|
)
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.get("/data_processing/settings")
|
|
async def get_settings():
|
|
try:
|
|
return MessageToDict(
|
|
stub.GetDataProcessingSettings(jfjoch_pb2.Empty()),
|
|
including_default_value_fields=True,
|
|
)
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.put("/data_processing/settings")
|
|
async def put_data_processing_settings(data: str = Body(...)):
|
|
try:
|
|
stub.PutDataProcessingSettings(Parse(data, jfjoch_pb2.DataProcessingSettings()))
|
|
return {}
|
|
except ParseError as e:
|
|
return HTTPException(status_code=400, detail="Parser error: " + str(e))
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.get("/data_processing/plots")
|
|
async def get_settings():
|
|
try:
|
|
return MessageToDict(
|
|
stub.GetPlots(jfjoch_pb2.Empty()), including_default_value_fields=True
|
|
)
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.put("/detector/measurement_statistics")
|
|
async def get_meas_stats():
|
|
try:
|
|
return MessageToDict(
|
|
stub.GetMeasurementStatistics(jfjoch_pb2.Empty()), including_default_value_fields=True
|
|
)
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
# https://stackoverflow.com/questions/55873174/how-do-i-return-an-image-in-fastapi
|
|
@app.get(
|
|
"/image/preview.tiff",
|
|
responses={200: {"content": {"image/tiff": {}}}},
|
|
response_class=Response,
|
|
)
|
|
async def get_preview():
|
|
try:
|
|
pbuf = stub.GetPreview(jfjoch_pb2.Empty())
|
|
image_array = numpy.frombuffer(pbuf.data, numpy.int16)
|
|
image_array = numpy.where(image_array < 0, -1, image_array)
|
|
image_array = numpy.reshape(image_array, (pbuf.height, pbuf.width))
|
|
b = BytesIO()
|
|
imwrite(b, image_array)
|
|
return Response(content=b.getvalue(), media_type="image/tiff")
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
def calib_to_tiff(im: jfjoch_pb2.Image) -> bytes:
|
|
if im.pixel_depth == 2:
|
|
image_array = numpy.frombuffer(im.data, numpy.uint16)
|
|
else:
|
|
image_array = numpy.frombuffer(im.data, numpy.uint32)
|
|
image_array = numpy.reshape(image_array, (im.height, im.width))
|
|
b = BytesIO()
|
|
imwrite(b, image_array)
|
|
return bytes(b.getvalue())
|
|
|
|
|
|
@app.get(
|
|
"/image/preview_dioptas.tiff",
|
|
responses={200: {"content": {"image/tiff": {}}}},
|
|
response_class=Response,
|
|
)
|
|
async def get_preview_dioptas():
|
|
try:
|
|
pbuf = stub.GetPreview(jfjoch_pb2.Empty())
|
|
if pbuf.pixel_depth == 2:
|
|
image_array = numpy.frombuffer(pbuf.data, numpy.int16)
|
|
else:
|
|
image_array = numpy.frombuffer(pbuf.data, numpy.int32)
|
|
image_array = numpy.where(image_array < 0, 32767, image_array)
|
|
image_array = numpy.reshape(image_array, (pbuf.height, pbuf.width))
|
|
image_array = numpy.flipud(image_array)
|
|
b = BytesIO()
|
|
imwrite(b, image_array)
|
|
return Response(content=b.getvalue(), media_type="image/tiff")
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.get(
|
|
"/image/pedestalG0.tiff",
|
|
responses={200: {"content": {"image/tiff": {}}}},
|
|
response_class=Response,
|
|
)
|
|
async def get_pedestalg0():
|
|
try:
|
|
pbuf = stub.GetPedestalG0(jfjoch_pb2.Empty())
|
|
return Response(content=calib_to_tiff(pbuf), media_type="image/tiff")
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.get(
|
|
"/image/pedestalG0.tiff",
|
|
responses={200: {"content": {"image/tiff": {}}}},
|
|
response_class=Response,
|
|
)
|
|
async def get_pedestalg1():
|
|
try:
|
|
pbuf = stub.GetPedestalG1(jfjoch_pb2.Empty())
|
|
return Response(content=calib_to_tiff(pbuf), media_type="image/tiff")
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.get(
|
|
"/image/pedestalG2.tiff",
|
|
responses={200: {"content": {"image/tiff": {}}}},
|
|
response_class=Response,
|
|
)
|
|
async def get_pedestalg2():
|
|
try:
|
|
pbuf = stub.GetPedestalG2(jfjoch_pb2.Empty())
|
|
return Response(content=calib_to_tiff(pbuf), media_type="image/tiff")
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|
|
|
|
|
|
@app.get(
|
|
"/image/mask.tiff",
|
|
responses={200: {"content": {"image/tiff": {}}}},
|
|
response_class=Response,
|
|
)
|
|
async def get_mask():
|
|
try:
|
|
pbuf = stub.GetMask(jfjoch_pb2.Empty())
|
|
return Response(content=calib_to_tiff(pbuf), media_type="image/tiff")
|
|
except grpc.RpcError as e:
|
|
raise HTTPException(status_code=400, detail=e.details())
|