add run command to CLI

This commit is contained in:
Christos Falas 2025-05-15 09:50:27 +01:00
parent 57fadd245a
commit 02eed8bf76
No known key found for this signature in database
3 changed files with 56 additions and 47 deletions

View File

@ -97,4 +97,6 @@ def _(proc: CSIMatrix) -> None:
cnt += 1
if __name__ == "__main__":
print("Starting app")
app.start()

View File

@ -166,9 +166,11 @@ class CSIApplication:
self.raw_csi_callback(sample.matrix)
if self.pre_merge_callback is not None:
self.pre_merge_callback(sample.frames)
processed = self.preprocessor.preprocess(sample.matrix, sample.frames)
if self.visualise_raw:
self.visualise_data(processed, visualise.figures.Figure.PROCESSED_CSI)
processed = self.preprocessor.preprocess(
sample.matrix, sample.frames, visualiser=self.visualise_data
)
# if self.visualise_raw:
# self.visualise_data(processed, visualise.figures.Figure.PROCESSED_CSI)
if self.preprocessed_csi_callback is not None:
self.preprocessed_csi_callback(processed)
@ -197,10 +199,13 @@ class CSIApplication:
self.buffer_thread.start()
self.webapp_thread.start()
if self.processing_callback is not None:
def get_proc_sample() -> None:
sample = self.preprocessor.last_sample
if self.visualise_raw and sample is not None:
self.visualise_data(
sample,
visualise.figures.Figure.PROCESSED_CSI,
)
if sample is not None and self.processing_callback is not None:
self.processing_callback(sample)
else:
@ -208,6 +213,7 @@ class CSIApplication:
self.scheduler = Scheduler(config.processing_sample_rate, get_proc_sample)
self.scheduler.start()
try:
self.webapp_thread.join()
except KeyboardInterrupt:

View File

@ -1,4 +1,6 @@
import importlib.util
import logging
from pathlib import Path
from queue import Queue
from typing import cast
@ -7,11 +9,11 @@ import numpy.typing as npt
import torch
import typer
from where_fi.application import CSIApplication
from where_fi.collection import CSIMatrix
from where_fi.config import config
from where_fi.processing.aoa import AoA
from ..application import CSIApplication
from ..config import config
from ..processing.aoa import AoA
from ..visualise import server as visualise
from . import file, globals
@ -53,44 +55,43 @@ def heatmap() -> None:
@cli.command()
def phase_analysis(
subcarriers: list[int] = [0], rx_antenna: int = 0, tx_antenna: int = 0
) -> None:
def run(file: Path, app_name: str = "app") -> None:
"""
Visualise the phase information in the CSI data received from the antennas.
Run the application with the given file.
The data goes through the same preprocessing steps as the heatmap command, but
instead of going through the AoA estimation, we simply analyse the phase of the
selected subcarrier and antenna.
Can be used for running arbitrary CSI applications with non-default data streams
(e.g. from file or environment simulation).
"""
print(file.absolute())
if not file.exists():
print(f"Error: File '{file}' does not exist.")
raise typer.Exit(1)
module_name = file.stem
app = CSIApplication(globals.csi_producer)
spec = importlib.util.spec_from_file_location(module_name, str(file))
if spec is None:
print(f"Could not load spec from {file}")
raise typer.Exit(1)
if isinstance(subcarriers, int):
subcarriers = [subcarriers]
print("Starting phase analysis on subcarriers: ", subcarriers)
module = importlib.util.module_from_spec(spec)
if spec.loader is None:
print(f"Could not load module from {file}")
raise typer.Exit(1)
try:
spec.loader.exec_module(module)
except Exception as e:
print(f"Failed to execute {file}: {e}")
raise typer.Exit(1) from e
subcarrier_phase: dict[int, Queue[float]] = {
x: Queue(config.collection_sample_rate) for x in subcarriers
}
if not hasattr(module, app_name):
print(f"Error: '{app_name}' not defined in the module.")
raise typer.Exit(1)
if not isinstance(module.app, CSIApplication):
print(f"Error: '{app_name}' is not a CSIApplication.")
raise typer.Exit(1)
@app.on_sample
def _(sample: CSIMatrix) -> None:
for subcarrier in subcarriers:
phase = cast(float, np.angle(sample[subcarrier, rx_antenna, tx_antenna]))
if subcarrier_phase[subcarrier].full():
subcarrier_phase[subcarrier].get()
subcarrier_phase[subcarrier].put(phase)
@app.on_process
def _(_: CSIMatrix) -> None:
logger.info("Updating phase visualisation")
app.visualise_data(
np.array([x.queue for x in subcarrier_phase.values()]),
visualise.figures.Figure.PHASE_ANALYSIS,
)
app.start()
module.app.producer = globals.csi_producer
module.app.start()
cli.add_typer(file.app, name="file", help="Commands for working with CSI files")