Skip to content

Commit ddc1e39

Browse files
committed
source catalog and line profile use source for images, handle missing ra, dec, add clientAlertExceptions to analysis endpoint
1 parent 14a3562 commit ddc1e39

File tree

3 files changed

+69
-28
lines changed

3 files changed

+69
-28
lines changed

datalab/datalab_session/analysis/line_profile.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def line_profile(input: dict):
2020
y2 (int): The y coordinate of the ending point
2121
}
2222
"""
23-
fits_path = get_fits(input['basename'])
23+
fits_path = get_fits(input['basename'], input['source'])
2424

2525
sci_hdu = get_hdu(fits_path, 'SCI')
2626

@@ -51,16 +51,16 @@ def line_profile(input: dict):
5151
position_angle = coordinates.position_angle(start_sky_coord.ra, start_sky_coord.dec,
5252
end_sky_coord.ra, end_sky_coord.dec).deg
5353
except WcsError:
54-
# no valid WCS solution
54+
# Can't calculate these values without WCS
5555
start_coords = None
5656
end_coords = None
5757
position_angle = None
5858

59+
# fallback attempt at using pixscale to calculate the arcsec distance
5960
try:
60-
# attempt using pixscale to calculate the angle
6161
arcsec_angle = len(line_profile) * sci_hdu.header["PIXSCALE"]
62-
except KeyError as e:
63-
# no valid WCS solution, and no pixscale
62+
except KeyError:
6463
arcsec_angle = None
6564

66-
return {"line_profile": line_profile, "arcsec": arcsec_angle, "start_coords": start_coords, "end_coords": end_coords, "position_angle": position_angle}
65+
line_profile_output = {"line_profile": line_profile, "arcsec": arcsec_angle, "start_coords": start_coords, "end_coords": end_coords, "position_angle": position_angle}
66+
return line_profile_output

datalab/datalab_session/analysis/source_catalog.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,28 @@
33
from datalab.datalab_session.file_utils import get_hdu, scale_points
44
from datalab.datalab_session.s3_utils import get_fits
55

6+
# Source catalog Function Definition
7+
# ARGS: input (dict)
8+
# input = {
9+
# basename (str): The name of the file to analyze
10+
# height (int): The height of the image
11+
# width (int): The width of the image
12+
# source (str): The source of the file
13+
# }
14+
# RETURNS: output (dict)
15+
# output = [{
16+
# x (int): The x coordinate of the source
17+
# y (int): The y coordinate of the source
18+
# flux (int): The flux value of the source
19+
# ra (float): The right ascension of the source
20+
# dec (float): The declination of the source
21+
# }]
22+
#
623
def source_catalog(input: dict):
724
"""
825
Returns a dict representing the source catalog data with x,y coordinates and flux values
926
"""
10-
fits_path = get_fits(input['basename'])
27+
fits_path = get_fits(input['basename'], input['source'])
1128

1229
cat_hdu = get_hdu(fits_path, 'CAT')
1330
sci_hdu = get_hdu(fits_path, 'SCI')
@@ -19,23 +36,30 @@ def source_catalog(input: dict):
1936
x_points = cat_hdu.data["x"][:SOURCE_CATALOG_COUNT]
2037
y_points = cat_hdu.data["y"][:SOURCE_CATALOG_COUNT]
2138
flux = cat_hdu.data["flux"][:SOURCE_CATALOG_COUNT]
22-
ra = cat_hdu.data["ra"][:SOURCE_CATALOG_COUNT]
23-
dec = cat_hdu.data["dec"][:SOURCE_CATALOG_COUNT]
39+
40+
# ra, dec values may or may not be present in the CAT hdu
41+
if "ra" in cat_hdu.data.names and "dec" in cat_hdu.data.names:
42+
ra = cat_hdu.data["ra"][:SOURCE_CATALOG_COUNT]
43+
dec = cat_hdu.data["dec"][:SOURCE_CATALOG_COUNT]
44+
else:
45+
# TODO: implement a fallback way to calculate ra, dec from x, y and WCS
46+
ra = np.zeros(SOURCE_CATALOG_COUNT)
47+
dec = np.zeros(SOURCE_CATALOG_COUNT)
2448

2549
# scale the x_points and y_points from the fits pixel coords to the jpg coords
2650
fits_height, fits_width = np.shape(sci_hdu.data)
2751
x_points, y_points = scale_points(fits_height, fits_width, input['width'], input['height'], x_points=x_points, y_points=y_points)
2852

29-
# we will be giving a list of dicts representing each source back to the frontend
53+
# create the list of source catalog objects
3054
source_catalog_data = []
3155
for i in range(SOURCE_CATALOG_COUNT):
3256
source_catalog_data.append({
3357
"x": x_points[i],
3458
"y": y_points[i],
3559
"flux": flux[i].astype(int),
36-
# truncate the ra and dec to 4 decimal places for readability
37-
"ra": '%.4f'%(ra[i]),
38-
"dec": '%.4f'%(dec[i])
60+
# Astronomical coordinates are formatted to 6 decimal places
61+
"ra": '%.6f'%(ra[i]),
62+
"dec": '%.6f'%(dec[i])
3963
})
4064

4165
return source_catalog_data

datalab/datalab_session/views.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import logging
2+
13
from rest_framework.generics import RetrieveAPIView
24
from rest_framework.renderers import JSONRenderer
35
from rest_framework.response import Response
@@ -7,6 +9,7 @@
79
from datalab.datalab_session.analysis.source_catalog import source_catalog
810
from datalab.datalab_session.analysis.get_tif import get_tif
911
from datalab.datalab_session.analysis.raw_data import raw_data
12+
from datalab.datalab_session.exceptions import ClientAlertException
1013

1114

1215
class OperationOptionsApiView(RetrieveAPIView):
@@ -26,18 +29,32 @@ class AnalysisView(RetrieveAPIView):
2629
To add a new analysis action, add a case to the switch statement and create a new file in the analysis directory
2730
"""
2831
def post(self, request, action):
29-
input = request.data
30-
31-
match action:
32-
case 'line-profile':
33-
output = line_profile(input)
34-
case 'source-catalog':
35-
output = source_catalog(input)
36-
case 'get-tif':
37-
output = get_tif(input)
38-
case 'raw-data':
39-
output = raw_data(input)
40-
case _:
41-
raise Exception(f'Analysis action {action} not found')
42-
43-
return Response(output)
32+
log = logging.getLogger()
33+
log.setLevel(logging.INFO)
34+
35+
try:
36+
# TODO replace switch case with an AnalysisAction class
37+
# AnalysisAction Class Definition
38+
# class AnalysisAction:
39+
# def __init__(self, action):
40+
# def run(self, input):
41+
# def name(self):
42+
input = request.data
43+
44+
match action:
45+
case 'line-profile':
46+
output = line_profile(input)
47+
case 'source-catalog':
48+
output = source_catalog(input)
49+
case 'get-tif':
50+
output = get_tif(input)
51+
case 'raw-data':
52+
output = raw_data(input)
53+
case _:
54+
raise Exception(f'Analysis action {action} not found')
55+
56+
return Response(output)
57+
58+
except ClientAlertException as error:
59+
log.error(f"Error running analysis action {action}: {error}")
60+
return Response({"error": f"Image doesn't support {action}"}, status=400)

0 commit comments

Comments
 (0)