From d196cd99d75b738995809d1f7c80ddb0d1265fc8 Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Fri, 8 Dec 2023 05:18:58 +0000 Subject: [PATCH] Implement gamutrf-offline. --- .github/workflows/docker-test.yml | 9 ++-- gamutrf/grscan.py | 5 +- gamutrf/grsource.py | 3 ++ gamutrf/offline.py | 90 +++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 gamutrf/offline.py diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index b9d68c60..52e3aad3 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -35,12 +35,13 @@ jobs: docker build -f docker/Dockerfile.base docker -t iqtlabs/gamutrf-base:latest docker build -f Dockerfile . -t iqtlabs/gamutrf:latest docker build -f docker/Dockerfile.torchsig . -t iqtlabs/gamutrf-torchsig:latest + docker run -t iqtlabs/gamutrf:latest gamutrf-compress_dirs --help + docker run -t iqtlabs/gamutrf:latest gamutrf-freqxlator --help + docker run -t iqtlabs/gamutrf:latest gamutrf-offline --help + docker run -t iqtlabs/gamutrf:latest gamutrf-samples2raw --help docker run -t iqtlabs/gamutrf:latest gamutrf-scan --help docker run -t iqtlabs/gamutrf:latest gamutrf-sigfinder --help - docker run -t iqtlabs/gamutrf:latest gamutrf-worker --help - docker run -t iqtlabs/gamutrf:latest gamutrf-samples2raw --help - docker run -t iqtlabs/gamutrf:latest gamutrf-freqxlator --help docker run -t iqtlabs/gamutrf:latest gamutrf-waterfall --help - docker run -t iqtlabs/gamutrf:latest gamutrf-compress_dirs --help + docker run -t iqtlabs/gamutrf:latest gamutrf-worker --help sudo apt-get update && sudo apt-get install -qy python3-pip docker compose -f orchestrator.yml -f worker.yml -f docker/monitoring.yml -f specgram.yml build diff --git a/gamutrf/grscan.py b/gamutrf/grscan.py index 3846740c..d002a0e8 100644 --- a/gamutrf/grscan.py +++ b/gamutrf/grscan.py @@ -169,6 +169,9 @@ def __init__( pretune, ) self.fft_blocks = fft_blocks + self.get_db_blocks(nfft, samp_rate, scaling) + fft_dir = sample_dir + if not write_samples: + fft_dir = "" retune_fft = self.iqtlabs.retune_fft( "rx_freq", nfft, @@ -181,7 +184,7 @@ def __init__( skip_tune_step, db_clamp_floor, db_clamp_ceil, - sample_dir, + fft_dir, write_samples, bucket_range, tuning_ranges, diff --git a/gamutrf/grsource.py b/gamutrf/grsource.py index 21ce5c3a..345af2a9 100644 --- a/gamutrf/grsource.py +++ b/gamutrf/grsource.py @@ -79,6 +79,9 @@ def work(self, input_items, output_items): self.need_tags = False n = len(output_items[0]) samples = self.samples[self.i : self.i + n] + if len(samples) < n: + self.i = self.n_samples + return 0 self.i += len(samples) output_items[0][:] = samples return len(samples) diff --git a/gamutrf/offline.py b/gamutrf/offline.py new file mode 100644 index 00000000..7968db58 --- /dev/null +++ b/gamutrf/offline.py @@ -0,0 +1,90 @@ +#!/usr/bin/python3 +from argparse import ArgumentParser, BooleanOptionalAction +import os +import logging +import tempfile +import time + +from gnuradio import iqtlabs +from gamutrf.grscan import grscan +from gamutrf.sample_reader import parse_filename + + +def argument_parser(): + parser = ArgumentParser() + parser.add_argument( + "filename", type=str, help="Recording filename" + ) + parser.add_argument( + "--tune-step-fft", + dest="tune_step_fft", + type=int, + default=512, + help="tune FFT step [default=%(default)r]", + ) + parser.add_argument( + "--vkfft", + dest="vkfft", + default=True, + action=BooleanOptionalAction, + help="use VkFFT", + ) + parser.add_argument( + "--db_clamp_floor", + dest="db_clamp_floor", + type=float, + default=-150, + help="clamp dB output floor", + ) + parser.add_argument( + "--db_clamp_ceil", + dest="db_clamp_ceil", + type=float, + default=50, + help="clamp dB output ceil", + ) + parser.add_argument( + "--nfft", + dest="nfft", + type=int, + default=1024, + help="FFTI size [default=%(default)r]", + ) + parser.add_argument( + "--n_image", + dest="n_image", + type=int, + default=10, + help="if > 1, only log 1/n images", + ) + return parser + + +def main(): + logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(message)s") + options = argument_parser().parse_args() + filename = options.filename + out_dir = os.path.dirname(filename) + meta = parse_filename(filename) + tb = grscan( + db_clamp_floor=-1e9, + fft_batch_size=256, + freq_end=0, + freq_start=meta["freq_center"], + inference_min_db=-1e9, + inference_output_dir=out_dir, + iqtlabs=iqtlabs, + n_image=options.n_image, + nfft=options.nfft, + pretune=True, + samp_rate=meta["sample_rate"], + sample_dir=out_dir, + sdr="file:" + filename, + tune_step_fft=options.tune_step_fft, + vkfft=options.vkfft, + ) + tb.start() + while not tb.sources[0].complete(): + time.sleep(1) + tb.stop() + tb.wait()