77from typing import cast
88
99import ijson
10-
1110from django .db import transaction
1211from django .db .models import QuerySet
1312from django .http import FileResponse
1918from drf_spectacular .utils import OpenApiResponse
2019from drf_spectacular .utils import extend_schema
2120from loguru import logger as log
22- from django .conf import settings
2321from opensearchpy import exceptions as os_exceptions
2422from rest_framework import status
2523from rest_framework import viewsets
5452 serialize_capture_or_composite ,
5553)
5654from sds_gateway .api_methods .tasks import start_capture_post_processing
55+ from sds_gateway .api_methods .throttling import VisStreamThrottle
5756from sds_gateway .api_methods .utils .asset_access_control import (
5857 user_has_access_to_capture ,
5958)
6665from sds_gateway .visualizations .models import ProcessingStatus
6766from sds_gateway .visualizations .processing .utils import reconstruct_drf_files
6867from sds_gateway .visualizations .processing .waterfall import FFT_SIZE
69- from sds_gateway .visualizations .processing .waterfall import get_waterfall_power_bounds
7068from sds_gateway .visualizations .processing .waterfall import SAMPLES_PER_SLICE
71- from sds_gateway .api_methods .throttling import VisStreamThrottle
7269from sds_gateway .visualizations .processing .waterfall import compute_slices_on_demand
70+ from sds_gateway .visualizations .processing .waterfall import get_waterfall_power_bounds
7371from sds_gateway .visualizations .serializers import PostProcessedDataSerializer
7472
7573MAX_CAPTURE_NAME_LENGTH = 255 # Maximum length for capture names
76- MAX_SLICE_BATCH_SIZE = 300 # Max slices per request (larger = fewer calls when fast-forwarding)
74+ MAX_SLICE_BATCH_SIZE = (
75+ 300 # Max slices per request (larger = fewer calls when fast-forwarding)
76+ )
7777
7878
7979def _validate_slice_indices (
@@ -163,9 +163,8 @@ def _extract_waterfall_slice_range(
163163 if total_slices_from_metadata is not None :
164164 total_slices = total_slices_from_metadata
165165 if start_index >= total_slices :
166- raise ValueError (
167- f"start_index ({ start_index } ) exceeds total slices ({ total_slices } )"
168- )
166+ msg = f"start_index ({ start_index } ) exceeds total slices ({ total_slices } )"
167+ raise ValueError (msg )
169168 end_index = min (end_index , total_slices )
170169 else :
171170 # One pass to count array length (no list storage)
@@ -178,20 +177,17 @@ def _extract_waterfall_slice_range(
178177 raise
179178 total_slices = count
180179 if start_index >= total_slices :
181- raise ValueError (
182- f"start_index ({ start_index } ) exceeds total slices ({ total_slices } )"
183- )
180+ msg = f"start_index ({ start_index } ) exceeds total slices ({ total_slices } )"
181+ raise ValueError (msg )
184182 end_index = min (end_index , total_slices )
185183 file_handle .seek (0 )
186184
187185 requested_slices : list [Any ] = []
188- current = 0
189- for item in ijson .items (file_handle , "item" ):
186+ for current , item in enumerate (ijson .items (file_handle , "item" )):
190187 if current >= end_index :
191188 break
192189 if current >= start_index :
193190 requested_slices .append (item )
194- current += 1
195191
196192 return requested_slices , total_slices
197193
@@ -409,13 +405,18 @@ def _get_processed_data_for_capture(
409405
410406 if not processed_data :
411407 hint = ""
412- if capture .capture_type == CaptureType .DigitalRF and processing_type == "waterfall" :
413- hint = " For DigitalRF captures, streaming mode may work without preprocessed data; otherwise run post-processing to generate waterfall data."
408+ if (
409+ capture .capture_type == CaptureType .DigitalRF
410+ and processing_type == "waterfall"
411+ ):
412+ hint = (
413+ " For DigitalRF captures, streaming mode may work without "
414+ "preprocessed data; otherwise run post-processing to generate "
415+ "waterfall data."
416+ )
414417 else :
415418 hint = " Run post-processing to generate this data."
416- msg = (
417- f"No completed { processing_type } data found for this capture.{ hint } "
418- )
419+ msg = f"No completed { processing_type } data found for this capture.{ hint } "
419420 raise Http404 (msg )
420421
421422 if not processed_data .data_file :
@@ -530,7 +531,7 @@ def _validate_create_request(
530531 def _handle_capture_creation_errors (
531532 self , capture : Capture , error : Exception
532533 ) -> Response :
533- """Handle errors during capture creation. Transaction auto-rolls back on error."""
534+ """Handle capture creation errors . Transaction auto-rolls back on error."""
534535 if isinstance (error , UnknownIndexError ):
535536 user_msg = f"Unknown index: '{ error } '. Try recreating this capture."
536537 server_msg = (
@@ -1178,9 +1179,7 @@ def download_post_processed_data(
11781179 ),
11791180 )
11801181 @action (detail = True , methods = ["get" ])
1181- def waterfall_slices ( # noqa: PLR0911
1182- self , request : Request , pk : str | None = None
1183- ) -> Response :
1182+ def waterfall_slices (self , request : Request , pk : str | None = None ) -> Response :
11841183 """Get waterfall slices by index range for streaming."""
11851184 # Get query parameters
11861185 processing_type = request .query_params .get ("processing_type" , "waterfall" )
@@ -1298,8 +1297,15 @@ def get_post_processed_metadata(
12981297
12991298 if not processed_data :
13001299 hint = ""
1301- if capture .capture_type == CaptureType .DigitalRF and processing_type == "waterfall" :
1302- hint = " For DigitalRF captures, streaming mode may work without preprocessed data; otherwise run post-processing to generate waterfall data."
1300+ if (
1301+ capture .capture_type == CaptureType .DigitalRF
1302+ and processing_type == "waterfall"
1303+ ):
1304+ hint = (
1305+ " For DigitalRF captures, streaming mode may work without "
1306+ "preprocessed data; otherwise run post-processing to generate "
1307+ "waterfall data."
1308+ )
13031309 else :
13041310 hint = " Run post-processing to generate this data."
13051311 return Response (
@@ -1331,9 +1337,9 @@ def get_post_processed_metadata(
13311337 required = False ,
13321338 default = False ,
13331339 description = (
1334- "If true, compute power_bounds (min/max dB) by sampling DRF data, "
1335- "which may trigger MinIO download and processing. Omit or false for "
1336- "fast metadata-only response."
1340+ "If true, compute power_bounds (min/max dB) by sampling DRF "
1341+ "data, which may trigger MinIO download and processing. Omit "
1342+ "or false for fast metadata-only response."
13371343 ),
13381344 ),
13391345 ],
@@ -1411,7 +1417,7 @@ def waterfall_metadata_stream(
14111417 status = status .HTTP_400_BAD_REQUEST ,
14121418 )
14131419
1414- # Bounds are in seconds (from DRF metadata: sample_index / samples_per_second)
1420+ # Bounds in seconds (DRF metadata: sample_index / samples_per_second)
14151421 duration_seconds = end_bound - start_bound
14161422 total_samples = int (duration_seconds * samples_per_second )
14171423 log .debug (
@@ -1446,9 +1452,7 @@ def waterfall_metadata_stream(
14461452 ).lower () in ("true" , "1" , "yes" )
14471453 if include_power_bounds :
14481454 try :
1449- capture_files = get_capture_files (
1450- capture , include_deleted = False
1451- )
1455+ capture_files = get_capture_files (capture , include_deleted = False )
14521456 if capture_files .exists ():
14531457 dummy_temp_path = Path (tempfile .gettempdir ()) / "unused"
14541458 drf_path = reconstruct_drf_files (
0 commit comments