1from logging import error
2from django.http import JsonResponse, HttpResponseBadRequest
3
4import chart
5
6from chart.db.model.exceptions import NoSuchTable
7from chart.db.model.table import find_param_by_name
8from chart.db.model.table import TableInfo
9from chart.project import SID
10from chart.project import settings
11
12from chart_rest.response_builder import single_linear
13from chart_rest.response_builder import correlation
14from chart_rest.response_builder import limits
15from chart_rest.response_builder import histogram
16from chart_rest.response_builder import csv
17from chart_rest.response_builder import bit_histogram
18from chart_rest.response_builder import textual_bar
19from chart_rest.response_builder import build_pspec
20from chart_rest.response_builder import geolocation_map
21from chart_rest.tree import build_events_tree
22from chart_rest.tree import build_table_tree
23from chart_rest.tree import build_main_tree
24from chart_rest.search import do_search
25
26from chart.plotviewer.plot_utils import PlotException
27from chart.plotviewer.plot_utils import PlotType
28
29# API Version for info endpoint
30API_VERSION = 0.1
31
32SID() # load all chart config
33
34
35def timeseries(request):
36 """
37 Handle timeseries request
38 """
39 try:
40 pspec = build_pspec(request)
41
42 # Create default plot
43 if pspec['ptype'] in (
44 PlotType.AUTO, PlotType.LINE,
45 PlotType.MINMAX, PlotType.BAR_O,
46 PlotType.BAR_S, PlotType.COVERAGE,
47 PlotType.GEO
48 ):
49 return JsonResponse(single_linear(pspec))
50 elif pspec['ptype'] is PlotType.GANTT:
51 return JsonResponse(textual_bar(pspec))
52 elif pspec['ptype'] is PlotType.CORRELATION:
53 correlation = correlation(pspec)
54
55 if correlation is None:
56 return JsonResponse(
57 {
58 "status": False,
59 "message": "No data found for time range"
60 }, status=404)
61 else:
62 return JsonResponse(correlation)
63
64 # Create limits plot
65 elif pspec['ptype'] is PlotType.LIMITS:
66 return JsonResponse(limits(pspec))
67
68 # Create histogram plot
69 elif pspec['ptype'] is PlotType.HISTO:
70 min_val = None
71 max_val = None
72 log_val = False
73 if len(pspec.get('axes', [])) >= 1:
74 ax = pspec['axes'][0]
75 min_val = ax.get('min')
76 max_val = ax.get('max')
77 log_val = ax.get('log', False)
78
79 hist = histogram(
80 pspec,
81 min_val=min_val,
82 max_val=max_val,
83 logscale=log_val
84 )
85
86 return JsonResponse(hist)
87
88 # Create bit histogram plot
89 elif pspec['ptype'] is PlotType.BITS:
90 return JsonResponse(bit_histogram(pspec))
91
92 # Return data for CSV export
93 elif pspec['ptype'] is PlotType.CSV:
94 return JsonResponse(csv(pspec))
95
96 except PlotException as e:
97 return JsonResponse(
98 {
99 "status": False,
100 "message": str(e)
101 }, status=500
102 )
103
104
105def info(request):
106 """
107 Handle domain info request
108 """
109
110 project_version = "N/A"
111 try:
112 project_version = settings.VERSION
113 except AttributeError:
114 ver = chart.project_version()
115 project_version = ver if ver is not None else "N/A"
116
117 chart_core_version = "N/A"
118 try:
119 chart_core_version = chart.__version__
120 except AttributeError:
121 ver = chart.version()
122 chart_core_version = ver if ver is not None else "N/A"
123
124 regions = []
125 try:
126 for s in SID.sampling_options:
127 regions.append(s.region)
128 except:
129 regions = SID.sampling_options()
130
131 return JsonResponse({
132 'project_version': project_version,
133 'core_version': chart_core_version,
134 'api_version': API_VERSION,
135 'stats': ['MIN', 'MAX', 'AVG', 'STD'], # These are hard-coded as in api2
136 'regions': regions,
137 'tables': sorted([t.name for t in TableInfo.all()]),
138 })
139
140
141def tables(request):
142 """
143 Handle table request
144 """
145
146 if "table" in request.GET:
147 # Return information about a single table."""
148 try:
149 table_info = TableInfo(request.GET['table'])
150
151 return JsonResponse(
152 {'name': table_info.name,
153 'description': table_info.description,
154 'has_stats': table_info.has_stats,
155 'common_fields': ['SENSING_TIME'],
156 'fields': [f for f in sorted(table_info.fields.keys())],
157 })
158 except NoSuchTable:
159 return JsonResponse({"status": False, "message": "Table not found"}, status=404)
160
161 else:
162 return JsonResponse({
163 'tables': sorted([t.name for t in TableInfo.all()]),
164 })
165
166def parameter(request):
167 """
168 Handle parameter metadata request
169 """
170
171 table_name = None
172 field_name = None
173 if "parameter" in request.GET:
174 parts = request.GET["parameter"].split(".")
175 if len(parts) == 2:
176 table_name = parts[0]
177 field_name = parts[1]
178
179 if table_name == None or field_name == None:
180 return JsonResponse({"status": False, "message": "Define parameter as table.field"}, status=400)
181
182 field_info = find_param_by_name(field=field_name, table=table_name)
183
184 if field_info:
185 choices = None
186 if field_info.choices != None:
187 choices = field_info.choices.items
188
189 return JsonResponse(
190 {
191 "name": field_info.name,
192 "description": field_info.description,
193 "unit": field_info.unit,
194 "datatype": field_info.datatype.name,
195 "calibration_name": field_info.calibration_name,
196 "choices": choices
197 })
198 else:
199 return JsonResponse({"status": False, "message": "Parameter not found"}, status=404)
200
201def tree(request):
202 """
203 Handle parameter tree request
204
205 Returns either table, events or main tree
206 """
207
208 table = None
209 sid_name = None
210 if "key" in request.GET:
211 table = request.GET["key"].split(".")[0]
212 if "sid" in request.GET:
213 sid_name = request.GET["sid"]
214
215 if table == "EVENTS":
216 res = build_events_tree()
217
218 elif table != None:
219 res = build_table_tree(table)
220
221 else:
222 res = build_main_tree(sid_name)
223
224 return JsonResponse(res)
225
226def search(request):
227 """
228 Search for events and parameters
229 based on any field, name, description or unit
230 """
231 any_field, name, description, unit, source = None, None, None, None, None
232
233 if "any" in request.GET:
234 any_field = request.GET["any"]
235 if "name" in request.GET:
236 name = request.GET["name"]
237 if "description" in request.GET:
238 description = request.GET["description"]
239 if "unit" in request.GET:
240 unit = request.GET["unit"]
241 if "source" in request.GET:
242 source = request.GET["source"]
243 if "sid" in request.GET:
244 sid_name = request.GET["sid"]
245
246 results = do_search(
247 any_field=any_field,
248 name=name,
249 description=description,
250 unit=unit,
251 source=source,
252 sid_name=sid_name)
253
254 return JsonResponse({"tree": results})
255
256def geolocation(request):
257 """
258 Get spacecraft latitude/longitude coordinates
259 """
260 pspec = build_pspec(request)
261
262 data = geolocation_map(pspec)
263
264 return JsonResponse(data)