diff --git a/spf/notebooks/load_real_data_session.ipynb b/spf/notebooks/load_real_data_session.ipynb index 02fd884e..8f52afd1 100644 --- a/spf/notebooks/load_real_data_session.ipynb +++ b/spf/notebooks/load_real_data_session.ipynb @@ -106,7 +106,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 7, @@ -127,19 +127,11 @@ "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "def get_peaks(beam_former_output):\n", - " first_peak=np.argmax(beam_former_output)\n", - "\n", - " pivot=16\n", - " if first_peak>32:\n", - " pivot=32+16\n", - "\n", - " d=np.abs(first_peak-pivot)\n", - " return pivot+d, pivot-d\n", + "from spf.rf import get_peaks_for_2rx\n", "\n", "idx=490\n", "bf_out=session['beam_former_outputs_at_t'][idx]\n", - "peaks=get_peaks(bf_out)\n", + "peaks=get_peaks_for_2rx(bf_out)\n", "plt.plot(bf_out,color='red',label=\"beamformer\")\n", "for peak in peaks:\n", " plt.axvline(x=peak,label=\"Peak\")\n", @@ -195,8 +187,8 @@ "axs[1,1].set_title(\"Ground truth theta\")\n", "\n", "#plot the beamformer output\n", - "peaks_at_t=np.array([ get_peaks(bf_out) for bf_out in session[\"beam_former_outputs_at_t\"]])\n", - "peaks_at_t_in_radians=2*(peaks_at_t/65-0.5)*np.pi\n", + "peaks_at_t=np.array([ get_peaks_for_2rx(bf_out) for bf_out in session[\"beam_former_outputs_at_t\"]])\n", + "peaks_at_t_in_radians=2*(peaks_at_t/session[\"beam_former_outputs_at_t\"].shape[1]-0.5)*np.pi\n", "peaks_at_t_in_radians_adjusted=(peaks_at_t_in_radians+20*session[\"detector_orientation_at_t\"]) #% (np.pi*2)\n", "\n", "axs[0,1].plot(peaks_at_t_in_radians_adjusted[:,0])\n", @@ -206,6 +198,22 @@ "\n", "f.tight_layout()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45e737e2", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2e53138", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/spf/notebooks/load_simulated_data_session.ipynb b/spf/notebooks/load_simulated_data_session.ipynb index dc4760df..2dabe291 100644 --- a/spf/notebooks/load_simulated_data_session.ipynb +++ b/spf/notebooks/load_simulated_data_session.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 48, "id": "59584a7c-1e24-4e41-9952-23e7298bc583", "metadata": {}, "outputs": [], @@ -16,18 +16,12 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 49, "id": "9eda4979", "metadata": {}, "outputs": [], "source": [ - "class dotdict(dict):\n", - " \"\"\"dot.notation access to dictionary attributes\"\"\"\n", - "\n", - " __getattr__ = dict.get\n", - " __setattr__ = dict.__setitem__\n", - " __delattr__ = dict.__delitem__\n", - "\n", + "from spf.utils import dotdict\n", "\n", "args=dotdict(\n", " {\n", @@ -62,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 50, "id": "3c05faba", "metadata": {}, "outputs": [], @@ -78,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 51, "id": "f76fd39b", "metadata": {}, "outputs": [], @@ -89,7 +83,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 52, "id": "7084912d-c62f-4383-a25b-79a6a99583f5", "metadata": {}, "outputs": [], @@ -101,17 +95,25 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, + "id": "3552f89f", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 53, "id": "21858d41-83af-4adb-b5cb-55e33b81c247", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 6, + "execution_count": 53, "metadata": {}, "output_type": "execute_result" }, @@ -129,19 +131,11 @@ "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "def get_peaks(beam_former_output):\n", - " first_peak=np.argmax(beam_former_output)\n", - "\n", - " pivot=16\n", - " if first_peak>32:\n", - " pivot=32+16\n", - "\n", - " d=np.abs(first_peak-pivot)\n", - " return pivot+d, pivot-d\n", + "from spf.rf import get_peaks_for_2rx\n", "\n", "idx=490\n", "bf_out=session['beam_former_outputs_at_t'][idx]\n", - "peaks=get_peaks(bf_out)\n", + "peaks=get_peaks_for_2rx(bf_out)\n", "plt.plot(bf_out,color='red',label=\"beamformer\")\n", "for peak in peaks:\n", " plt.axvline(x=peak,label=\"Peak\")\n", @@ -150,7 +144,15 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, + "id": "f700afb8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 54, "id": "ab349f95-e442-4b52-b1dc-b18e1748874c", "metadata": {}, "outputs": [ @@ -189,8 +191,8 @@ "axs[1,1].set_title(\"Ground truth theta\")\n", "\n", "#plot the beamformer output\n", - "peaks_at_t=np.array([ get_peaks(bf_out) for bf_out in session[\"beam_former_outputs_at_t\"]])\n", - "peaks_at_t_in_radians=2*(peaks_at_t/65-0.5)*np.pi\n", + "peaks_at_t=np.array([ get_peaks_for_2rx(bf_out) for bf_out in session[\"beam_former_outputs_at_t\"]])\n", + "peaks_at_t_in_radians=2*(peaks_at_t/args.beam_former_spacing-0.5)*np.pi\n", "peaks_at_t_in_radians_adjusted=(peaks_at_t_in_radians+20*session[\"detector_orientation_at_t\"]) #% (np.pi*2)\n", "\n", "axs[0,1].plot(peaks_at_t_in_radians_adjusted[:,0])\n", @@ -203,9 +205,78 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 55, "id": "cb653ce9", "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[-0.53165414, -2.65827071],\n", + " [-0.53165414, -2.65827071],\n", + " [-0.43498975, -2.7549351 ],\n", + " ...,\n", + " [-1.01497609, -2.17494876],\n", + " [-1.01497609, -2.17494876],\n", + " [-1.11164048, -2.07828437]])" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "peaks_at_t=np.array([ get_peaks_for_2rx(bf_out) for bf_out in session[\"beam_former_outputs_at_t\"]])\n", + "peaks_at_t_in_radians=2*(peaks_at_t/args.beam_former_spacing-0.5)*np.pi\n", + "peaks_at_t_in_radians_adjusted=(peaks_at_t_in_radians+session[\"detector_orientation_at_t\"]) #% (np.pi*2)\n", + "peaks_at_t_in_radians_adjusted" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "cd929e75", + "metadata": {}, + "outputs": [], + "source": [ + "ground_truth=session[\"detector_orientation_at_t\"]+ session[\"source_theta_at_t\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "c5ebdfb6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.08651613092957919" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.abs(peaks_at_t_in_radians_adjusted-ground_truth).min(axis=1).mean()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef694ea5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1062621d", + "metadata": {}, "outputs": [], "source": [] } diff --git a/spf/rf.py b/spf/rf.py index 118ad4b1..9a4e83cb 100644 --- a/spf/rf.py +++ b/spf/rf.py @@ -73,7 +73,6 @@ def __init__(self, pos, frequency, phase=0, amplitude=1): self.amplitude = amplitude def signal(self, sampling_times): - # return np.cos(2*np.pi*sampling_times*self.frequency+self.phase)+np.sin(2*np.pi*sampling_times*self.frequency+self.phase)*1j return self.amplitude * np.sin( 2 * np.pi * sampling_times * self.frequency + self.phase ) # .reshape(1,-1) @@ -378,3 +377,15 @@ def beamformer( ) # this is adjust and sum in one step steer_dot_signal = np.absolute(phase_adjusted).mean(axis=1) # mean over samples return thetas, steer_dot_signal, steering_vectors + + +def get_peaks_for_2rx(beam_former_output): + n = beam_former_output.shape[0] + first_peak = np.argmax(beam_former_output) + + pivot = n // 4 + if first_peak > n // 2: + pivot = n // 2 + n // 4 + + d = np.abs(first_peak - pivot) + return pivot + d, pivot - d diff --git a/tests/test_dataset.py b/tests/test_dataset.py index 60d6c1d4..6d4e1852 100644 --- a/tests/test_dataset.py +++ b/tests/test_dataset.py @@ -1,10 +1,12 @@ import tempfile +import numpy as np import pytest from compress_pickle import dump +from spf.dataset.spf_dataset import SessionsDataset from spf.dataset.spf_generate import generate_session_and_dump - +from spf.rf import get_peaks_for_2rx from spf.utils import dotdict @@ -28,12 +30,12 @@ def default_args(): "detector_speed": 10.0, "source_speed": 0.0, "sigma_noise": 1.0, - "time_steps": 100, + "time_steps": 1024, "time_interval": 0.3, "readings_per_snapshot": 3, - "sessions": 16, + "sessions": 2, "reference": False, - "cpus": 8, + "cpus": 2, "live": False, "profile": False, "fixed_detector": None, # @@ -54,13 +56,60 @@ def test_data_generation(default_args): generate_session_and_dump((args, session_idx)) for session_idx in range(args.sessions) ] - # ds = Sessions + ds = SessionsDataset(root_dir=tmp, snapshots_in_sample=1024) + session = ds[1] + dump( + session, + "/".join([args.output, "onesession.pkl"]), + compression="lzma", + ) + + +def test_closeness_to_ground_truth(default_args): + with tempfile.TemporaryDirectory() as tmp: + args = default_args + args.output = tmp + args.live = True + args.sources = 1 + args.elements = 2 + args.detector_speed = 0.0 + args.source_speed = 10.0 + args.sigma_noise = 0.0 + args.detector_noise = 0.0 + args.beam_former_spacing = 4096 + 1 + dump( + args, + "/".join([args.output, "args.pkl"]), + compression="lzma", + ) + ds = SessionsDataset(root_dir=tmp, snapshots_in_sample=1024) + session = ds[1] + peaks_at_t = np.array( + [ + get_peaks_for_2rx(bf_out) + for bf_out in session["beam_former_outputs_at_t"] + ] + ) + peaks_at_t_in_radians = ( + 2 * (peaks_at_t / args.beam_former_spacing - 0.5) * np.pi + ) + peaks_at_t_in_radians_adjusted = ( + peaks_at_t_in_radians + session["detector_orientation_at_t"] + ) + ground_truth = ( + session["detector_orientation_at_t"] + session["source_theta_at_t"] + ) + deviation = ( + np.abs(peaks_at_t_in_radians_adjusted - ground_truth).min(axis=1).mean() + ) + assert deviation < 0.01 def test_live_data_generation(default_args): with tempfile.TemporaryDirectory() as tmp: args = default_args args.output = tmp + args.live = True dump( args, "/".join([args.output, "args.pkl"]), @@ -70,3 +119,10 @@ def test_live_data_generation(default_args): generate_session_and_dump((args, session_idx)) for session_idx in range(args.sessions) ] + ds = SessionsDataset(root_dir=tmp, snapshots_in_sample=1024) + session = ds[1] + dump( + session, + "/".join([args.output, "onesession.pkl"]), + compression="lzma", + )