diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..79847cc73fd2e2d4b0e5eb36b24f2f78b3aab53e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,35 +1,6 @@ -*.7z filter=lfs diff=lfs merge=lfs -text -*.arrow filter=lfs diff=lfs merge=lfs -text -*.bin filter=lfs diff=lfs merge=lfs -text -*.bz2 filter=lfs diff=lfs merge=lfs -text -*.ckpt filter=lfs diff=lfs merge=lfs -text -*.ftz filter=lfs diff=lfs merge=lfs -text -*.gz filter=lfs diff=lfs merge=lfs -text -*.h5 filter=lfs diff=lfs merge=lfs -text -*.joblib filter=lfs diff=lfs merge=lfs -text -*.lfs.* filter=lfs diff=lfs merge=lfs -text -*.mlmodel filter=lfs diff=lfs merge=lfs -text -*.model filter=lfs diff=lfs merge=lfs -text -*.msgpack filter=lfs diff=lfs merge=lfs -text -*.npy filter=lfs diff=lfs merge=lfs -text -*.npz filter=lfs diff=lfs merge=lfs -text -*.onnx filter=lfs diff=lfs merge=lfs -text -*.ot filter=lfs diff=lfs merge=lfs -text -*.parquet filter=lfs diff=lfs merge=lfs -text -*.pb filter=lfs diff=lfs merge=lfs -text -*.pickle filter=lfs diff=lfs merge=lfs -text -*.pkl filter=lfs diff=lfs merge=lfs -text -*.pt filter=lfs diff=lfs merge=lfs -text -*.pth filter=lfs diff=lfs merge=lfs -text -*.rar filter=lfs diff=lfs merge=lfs -text -*.safetensors filter=lfs diff=lfs merge=lfs -text -saved_model/**/* filter=lfs diff=lfs merge=lfs -text -*.tar.* filter=lfs diff=lfs merge=lfs -text -*.tar filter=lfs diff=lfs merge=lfs -text -*.tflite filter=lfs diff=lfs merge=lfs -text -*.tgz filter=lfs diff=lfs merge=lfs -text -*.wasm filter=lfs diff=lfs merge=lfs -text -*.xz filter=lfs diff=lfs merge=lfs -text -*.zip filter=lfs diff=lfs merge=lfs -text -*.zst filter=lfs diff=lfs merge=lfs -text -*tfevents* filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text +*.jpeg filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..925846e2e01fe3f3fb4b115f3e4c19597b507a2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,117 @@ +# Python +__pycache__/ +*.py[cod] +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual Environments +venv/ +ENV/ +env/ +.venv/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store + +# Jupyter Notebook +.ipynb_checkpoints/ + +# PyTorch +*.pt.tmp +*.ckpt +*.pth.tar +*.safetensors + +# Training checkpoints are not shipped - the app only loads results/.pt +latest_checkpoint.pt + +# ============================================================ +# Commit policy +# GitHub repo : code only - what is needed to run the app +# Download : pre-trained weights and the datasets are published +# separately (download link to be announced) +# ============================================================ + +# Old repository backup, kept locally only +.git.backup-*/ + +# Weights (~2.5 GB) and datasets never go through GitHub +ckpts/ + + +# Onboarding notes / HF Space card, kept in the Hugging Face mirror +environment.yml +DEPLOY.md +HF_README.md + +checkpoints/ +pretrained/ +weights/ + +# Data files (large files) +data/ +*.mat +*.h5 +*.hdf5 +*.npz + +# Exception: the logos are needed by the README and the app header +!logos/*.png +!logos/*.jpg + +# Exception: the README screenshots ship with the repository +!images/*.png +!images/*.jpg + +# Exception: transmit signals and window coefficients are tiny (KB) and required +# at runtime by the traditional-processing pipeline +!datasets/*/coefs/*.mat + +# huggingface_hub 下载/上传时产生的本地缓存 +.cache/ + +# Logs +*.log +logs/ + +# Temporary files +tmp/ +temp/ +*.tmp + +# Backup files (e.g. the *.onehot.npy.bak produced by the annotation converter) +*.bak + +# Environment variables +.env +.env.local + +# Gradio cache +.gradio/ +flagged/ + +# Archives +*.zip +*.tar.gz +*.rar +*.7z diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..2abd2a24518190ddc59c71c93544575366abc102 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 End-to-End Radar Echo Segmentation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 32897cd3e640101ba184f8c4ccd896981de3804a..c16b41b335f80e8ab1d008d490d91a4479476584 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,293 @@ --- license: mit +tags: + - radar + - semantic-segmentation + - gradio --- + +![Perception & Cognition Laboratory (PeCoLab)](logos/peco-logo-banner-yellow.png) + +# End-to-End Radar Echo Segmentation Visualization + +[![Gradio](https://img.shields.io/badge/Gradio-6.0%2B-orange.svg)](https://gradio.app/) +[![PyTorch](https://img.shields.io/badge/PyTorch-2.0+-red.svg)](https://pytorch.org/) +[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) + +A comprehensive visualization tool for end-to-end radar echo segmentation, supporting multiple deep learning models and comparison with traditional signal processing methods. + +## Overview + +This project provides an interactive web interface for radar echo data segmentation using state-of-the-art deep learning models. It allows users to: + +- Visualize radar echo segmentation results from multiple models +- Compare deep learning approaches with traditional signal processing (LMF, MTI, MTD, CFAR) +- Perform side-by-side model comparisons + +> **Data availability:** this repository ships **sample data only** — one frame per +> scenario for each dataset — so the app runs out of the box and every feature can be +> tried. The **full Syn-RED and HiL-RED datasets must be downloaded separately**; +> the download link will be published here once available. See +> [Datasets](#datasets) for details. + +## Screenshots + +**EchMo vs. Traditional RSP** — the segmentation result (raw echo, ground truth, +EchMo + CFAR overlay) next to the EchMo intermediate features (LMF / MLDC / GDF) and the +traditional pipeline (LMF / MTI / MTD), shown for a HiL-RED deceptive-jamming sequence +with the "ALL 3D" view enabled. + +![EchMo vs. Traditional RSP tab](images/screenshot_echmo_vs_traditional.png) + +**Model Comparison** — the same frame segmented by EchMo, TMVA-Net, DeepLabV3+, U-Net, +FCN-8s and ViT side by side, together with the raw echo, the MTD input and the ground truth. + +![Model Comparison tab](images/screenshot_model_comparison.png) + +## Supported Models + +| Model | Description | +|-------|-------------| +| **EchMo** | End-to-end Complex-valued Hierarchical Model (proposed method) | +| **U-Net** | Classic convolutional encoder-decoder architecture | +| **DeepLabV3+** | DeepLabV3+ with ResNet-101 backbone | +| **FCN-8s** | Fully Convolutional Network with 8x upsampling | +| **TMVA-Net** | Temporal Multi-View Attention Network | +| **ViT** | Vision Transformer for semantic segmentation | + +## Datasets + +> **This repository ships sample data only** — for Syn-RED one frame per +> distance/motion/SNR scenario, for HiL-RED one frame per jamming scenario — together +> with all pre-trained weights. This is enough to run the app end to end and to try +> every feature, but it is **not the full benchmark data**. +> +> **The full Syn-RED and HiL-RED datasets must be downloaded separately**; the +> download link will be published here as soon as it is available. Once downloaded, +> unpack the full datasets into `datasets/` (merging with the sample folders) — no +> code change is needed, new sequences and frames are discovered automatically. + +The application supports the two echo datasets introduced in the paper, +**Syn-RED** and **HiL-RED**: + +### Syn-RED — Synthetic Radar Echo Dataset +Low-slow-small (LSS) target detection, built by precise electromagnetic simulation. + +- Controlled target scenes with varying motion characteristics and SNRs +- Multiple distances (1000m, 3000m, 5000m) +- Motion types: Line, O-shape, S-shape (Hover scenarios exist in the raw data but are not exposed in the UI) +- SNR levels: 10 dB, 14 dB, 18 dB +- 2 annotated classes: background, target + +### HiL-RED — Hardware-in-the-Loop Radar Echo Dataset +Target-jammer recognition under active electronic countermeasures, captured on a +hardware-in-the-loop platform that incorporates radar interference types and JSR. + +- Jamming types: Barrage (narrow/wide), Deceptive (DFT / ISR / SLI) +- Jamming intensities: -10 dB, -15 dB, -20 dB +- 7 annotated classes (background, target, DFTJ, ISRJ, SIJ, WJ, NJ); the networks are +trained with 9 output channels + +Each dataset folder carries a `dataset_meta.json` that declares dataset-specific +behaviour (MTD `fftshift`, the MTD amplitude folder, the classes offered by the UI +filter). Adding a dataset means dropping in a folder — no code change needed. +Model runs are discovered from `models//*/config.json` (the folder must +contain `"model": "..."` and `results/.pt`). When a dataset holds several +runs of the same model the alphabetically first one wins, and +`"run_overrides": {"model": "run_folder"}` in `dataset_meta.json` pins a specific +one - useful when e.g. a 7-class and a 9-class HiL-RED checkpoint coexist. + +## Features + +### Single Model Tab +- Visualize intermediate features from EchMo (LMF, MLDC, GDF) +- Compare with traditional RSP methods +- Display raw echo input, ground truth, and prediction masks + +### Model Comparison Tab +- Run inference with all 6 models simultaneously +- Side-by-side visualization of segmentation results +- Easy comparison of model performance + +## Download & Local Deployment + +Everything needed to run the app is hosted in this repository: the code, the +pre-trained weights (~2 GB) and **sample data** for both datasets (one frame per +scenario — the full datasets will be distributed separately, see +[Datasets](#datasets)). + +### Step 1 — Download this repository + +Option A — `huggingface_hub` (recommended, no Git required): + +```bash +pip install -U "huggingface_hub[cli]" +huggingface-cli download fxy0111/EchMo-Vis --local-dir EchMo-Vis +cd EchMo-Vis +``` + +Option B — Git (requires [Git LFS](https://git-lfs.com); the weights and `.npy` data +are stored in LFS, a plain `git clone` without LFS only downloads pointer files): + +```bash +git lfs install +git clone https://huggingface.co/fxy0111/EchMo-Vis +cd EchMo-Vis +``` + +> While the repository is **private**, authenticate first with a token from +> (read permission is enough): +> `huggingface-cli login`. Once the repository is public, no login is needed. + +The layout the app expects: + +``` +/ +├── app.py +├── models///config.json # layer/hyper-params +├── models///results/.pt # weights +└── datasets// + ├── light_dataset_frame_oriented.json # sequence / frame index + ├── dataset_meta.json # per-dataset behaviour + ├── coefs/s_tx.mat # transmit reference + └── /range_doppler_echo/.npy # echo data + └── /annotations/dense//range_doppler.npy # ground truth + └── //.npy # MTD amplitude (see dataset_meta.json) +``` +> **Heads-up:** model runs are discovered from `models//*/config.json` and +> datasets from `datasets/*/light_dataset_frame_oriented.json`. When something is missing the +> app does **not** raise: the dataset simply does not appear in the data-source dropdown, or a +> model is skipped in the comparison tab with only a console warning. Other errors surface only +> on Run ("Echo data not found", "Model file not found: ...") - so make sure Step 1 actually +> produced the layout above. + +### Note on the pre-trained weights (epoch-291 exports) + +The weights under `models/` are a subset copy of the training artifacts kept in +`ckpts/`. Please be aware: + +- For **HiL-RED**, the deeplabv3plus, unet, vit and fcn8s weights were exported + from **epoch 291** instead of the best epoch recorded in the training logs, so + the metrics these four models show in the app are **lower than the paper + values**. echmo and tmva_net_sv are not affected. +- For **Syn-RED**, the vit weight is likewise a slightly non-best export + (Δ0.007 mIoU). +- **The results reported in the paper are unaffected**: they were taken from the + best epoch of the TensorBoard logs, which are shipped under + `ckpts///boards/`. + +The full run tables and TensorBoard logs live in the training repository under +`ckpts///boards/` (not shipped in this repository). + +### Step 2 — Install and run + +```bash +# Install dependencies +pip install -r requirements.txt + +# Run the application +python app.py +``` + +Then open `http://localhost:7860` in a browser (override the port with the `PORT` +environment variable). Inference runs on GPU automatically when CUDA is available, +otherwise on CPU. + +## File Structure + +``` +. +├── app.py # Main Gradio application +├── asset_paths.py # single source of truth for dataset/model paths +├── requirements.txt # Python dependencies +├── README.md # This file +├── logos/ # PeCoLab banner + header logo +│ ├── logo.jpg # app header logo (app.py: LOGO_PATH) +│ └── peco-logo-banner-yellow.png +├── models/ # Model definitions + pre-trained weights +│ ├── echmo.py +│ ├── unet.py +│ ├── deeplabv3plus.py +│ ├── fcn8s.py +│ ├── tmva_net_sv.py +│ ├── vit.py +│ ├── Syn-RED/ # config.json + results/*.pt +│ └── HiL-RED/ # config.json + results/*.pt +└── datasets/ # demo subset of both datasets + ├── Syn-RED/ + └── HiL-RED/ +``` + +`dataset_meta.json` declares the dataset-specific behaviour (MTD `fftshift`, the MTD +amplitude folder, the classes offered by the UI filter); `run_overrides` can pin a +specific model run when a dataset holds several of them. + +## Usage + +### Using Pre-loaded Datasets + +1. Select a **Data Source** (Syn-RED or HiL-RED) +2. Choose a **Sequence** from the dropdown +3. Select a **Frame** to visualize +4. Click **Run** to see the results + +### Model Comparison + +1. Switch to the **Model Comparison** tab +2. Select data source, sequence, and frame +3. Click **Run** to compare all models side-by-side + +## Input Data Format + +### Transmit Signal (.mat or .npy) +- Complex-valued signal +- Shape: `(2, N)` or `(N,)` where N is signal length +- For .mat files: variable name should be `s_tx`, `st`, `transmit`, `tx_signal`, or `s` + +### Echo Signal (.npy) +- Complex-valued radar echo data +- Shape: `(2, Doppler, Range)` or `(Doppler, Range)` +- Channel 0: Real part, Channel 1: Imaginary part (if 3D) + +### Ground-truth Annotation (.npy) +Both layouts are accepted (see `annotation_to_label_map()` in `app.py`): + +- **one-hot** `(C, Doppler, Range)`: every pixel has exactly one hot channel, the app + applies `argmax(axis=0)`. Syn-RED uses this (`C=2`, `uint8`). +- **label map** `(Doppler, Range)`: one integer class id per pixel, used as-is. + HiL-RED ships this form (`int8`), converted from the original 9-channel `float64` + one-hot (~72x smaller, lossless). + +HiL-RED uses class ids **0-6** only; some checkpoints were trained with 9 output +channels (the last two are always empty), which is handled automatically because +`nb_classes` is read from each run's `config.json`. + +## Technical Details + +### EchMo Model Architecture + +The EchMo model consists of three main components: + +1. **LMF (Learnable Matched Filter)** - Adaptive matched filtering +2. **MLDC (Multi-Level Deep Convolution)** - Hierarchical feature extraction +3. **GDF (Gated Doppler Fusion)** - Doppler-aware feature fusion + +### Traditional Signal Processing Pipeline + +1. **LMF** - Linear Matched Filtering +2. **MTI** - Moving Target Indication (clutter suppression) +3. **MTD** - Moving Target Detection (Doppler processing) +4. **CFAR** - Constant False Alarm Rate detection + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +## Acknowledgments + +- This work was developed for radar signal processing research +- Thanks to the open-source community for PyTorch, Gradio, and other tools + +## Contact + +For questions or issues, please open an issue on GitHub or contact the authors. diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..1054efa9acd6eff8e1932060a1973037e19db429 --- /dev/null +++ b/app.py @@ -0,0 +1,4890 @@ +""" +End-to-End Radar Echo Segmentation Visualization +""" + +import os +import json +import math +import time +import numpy as np + +# Import pandas early and touch an attribute to avoid a circular-import problem during Plotly serialisation +import pandas +pandas.Series # Touch an attribute to make sure pandas is fully initialised + +from scipy.fftpack import fft, fftshift +import torch +import torch.nn as nn +import torch.nn.functional as F +import gradio as gr +import matplotlib.pyplot as plt +import matplotlib +matplotlib.use('Agg') +from matplotlib.colors import ListedColormap +from pathlib import Path +from scipy.io import loadmat +import scipy.io as scio +import torch.nn.init as init +import io +import base64 +from PIL import Image +import plotly.graph_objs as go +import tempfile +import matplotlib.colors as mcolors +from collections import OrderedDict +import traceback + + +# ==================== Configuration ==================== +DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + +# ==================== Logo Configuration ==================== +# NOTE: the logo now lives in logos/, keep this in sync if the path changes +LOGO_PATH = os.path.join("logos", "logo.jpg") + + +def get_logo_base64(): + """Read the logo image and convert it to base64""" + try: + with open(LOGO_PATH, "rb") as f: + return base64.b64encode(f.read()).decode() + except Exception as e: + print(f"[warn] Could not load logo from '{LOGO_PATH}': {e}") + return "" + + +LOGO_BASE64 = get_logo_base64() + +# ==================== Model Path Configuration ==================== +# Model runs are discovered from disk at runtime, see asset_paths.discover_runs(): +# models///config.json -> declares the model name +# models///results/.pt +# Nothing has to be maintained here when a dataset is added or a model is retrained. + +# Default model and dataset metadata +DEFAULT_MODEL = 'echmo' + +# Colour configuration - for the segmentation masks and the UI +COLORS = { + 'background': "#444486", + 'surface': '#14141f', + 'panel': '#1a1a2e', + 'primary': '#7c3aed', + 'secondary': '#f59e0b', + 'accent': '#06b6d4', + 'text': '#e2e8f0', + 'text_dim': '#94a3b8', + 'border': '#2d2d44', +} + +# Segmentation colors (RGB) - make sure these colors are used consistently +SEG_COLORS_2 = [ + "#440154", # 1. dark purple (fixed - background) + "#FDE725", # 2. bright yellow (fixed - main target) +] + +SEG_COLORS_9 = [ + "#440154", # 1. dark purple (fixed - background) + "#FDE725", # 2. bright yellow (fixed - main target) + # -------------------------- + # First group: three **similar purple** entries + "#B71C1C", # 3. deep red (darkest, base) + "#E53935", # 4. red (middle, main red) + "#EF9A9A", # 5. light red (brightest, pink) + # -------------------------- + # Second group: two **similar teal/green** entries + "#2563EB", # 3. dodger blue + "#7DD3FC", # 5. light sky blue + # -------------------------- + # Finish the Viridis ramp (9 colours in total) + "#45CA77", # 8. grass green + "#84E354" # 9. yellow green +] + +# Local module: single source of truth for dataset / model paths (standard library only) +import asset_paths as assets + +# Import all models for comparison +from models.echmo import EchMo +from models.unet import UNet +from models.deeplabv3plus import DeepLabV3Plus_Res101, DeepLabV3 +from models.fcn8s import FCN8s +from models.tmva_net_sv import TMVANet_SV +from models.vit import ViT + +# ==================== Traditional Signal Processing ==================== + +def load_transmit_signal(dataset_path, dataset_name): + """Load the transmit signal from a .mat file""" + tx_path = os.path.join(dataset_path, 'coefs', 's_tx.mat') + + if not os.path.exists(tx_path): + raise FileNotFoundError(f"Transmit signal not found: {tx_path}") + + mat_data = loadmat(tx_path) + + # Locate the transmit-signal variable + s_tx = None + var_name = None + + if 's_tx' in mat_data: + s_tx = mat_data['s_tx'] + var_name = 's_tx' + elif 'st' in mat_data: + s_tx = mat_data['st'] + var_name = 'st' + else: + for key in mat_data.keys(): + if not key.startswith('__'): + s_tx = mat_data[key] + var_name = key + break + + if s_tx is None: + raise ValueError(f"No valid transmit signal found in {tx_path}") + + print(f"[DEBUG] {dataset_name}: Loaded '{var_name}' shape={s_tx.shape}, dtype={s_tx.dtype}") + + return s_tx + + +def load_transmit_signal_from_file(file_path): + """ + Load the transmit signal from an uploaded file (.mat or .npy) + """ + if file_path is None: + raise ValueError("Please upload a transmit signal file") + + file_ext = os.path.splitext(file_path)[1].lower() + + if file_ext == '.mat': + mat_data = loadmat(file_path) + s_tx = None + var_name = None + + for key in ['s_tx', 'st', 'transmit', 'tx_signal', 's']: + if key in mat_data: + s_tx = mat_data[key] + var_name = key + break + + if s_tx is None: + for key in mat_data.keys(): + if not key.startswith('__'): + s_tx = mat_data[key] + var_name = key + break + + if s_tx is None: + raise ValueError(f"No valid transmit signal found in {file_path}") + + print(f"[DEBUG] Loaded transmit signal '{var_name}' shape={s_tx.shape}, dtype={s_tx.dtype}") + return s_tx + + elif file_ext == '.npy': + s_tx = np.load(file_path) + print(f"[DEBUG] Loaded transmit signal from .npy shape={s_tx.shape}, dtype={s_tx.dtype}") + return s_tx + + else: + raise ValueError(f"Unsupported file format: {file_ext}. Please use .mat or .npy") + + +def traditional_lmf_mti_mtd(raw_data, dataset_name=None, dataset_path=None, tx_signal=None): + """ + Traditional signal processing using actual transmit signal + """ + + if raw_data.shape[0] == 2: + raw_cmplx = raw_data[0] + 1j * raw_data[1] + else: + raw_cmplx = raw_data + + signal_len = raw_cmplx.shape[1] + + # Load the actual transmit signal + if tx_signal is not None: + s_tx = tx_signal + print(f"[DEBUG] Using uploaded transmit signal shape={s_tx.shape}") + elif dataset_path is not None and dataset_name is not None: + s_tx = load_transmit_signal(dataset_path, dataset_name) + else: + raise ValueError("Either tx_signal or (dataset_path and dataset_name) must be provided") + + # Handle the transmit-signal format + if s_tx.ndim == 2: + if s_tx.shape[0] == 2: + mf = s_tx[0] + 1j * s_tx[1] + else: + mf = s_tx[:, 0] + 1j * s_tx[:, 1] if s_tx.shape[1] == 2 else s_tx.flatten() + else: + mf = s_tx.flatten() + + mf = np.asarray(mf, dtype=np.complex64) + N_mf = len(mf) + + print(f"[DEBUG] Transmit signal length: {N_mf}") + + # option 1: no pre-flip + mf_padded = np.zeros(signal_len, dtype=np.complex64) + mf_padded[:N_mf] = mf + mf_fft = np.conj(np.fft.fft(mf_padded)) + + # multiply in the FFT domain + fft_raw = np.fft.fft(raw_cmplx, axis=1) + lmf_fft = fft_raw * mf_fft + lmf_data = np.fft.ifft(lmf_fft, axis=1) + + print(f"[DEBUG] LMF output max at: {np.unravel_index(np.argmax(np.abs(lmf_data)), lmf_data.shape)}") + + # MTI + mti_data = np.zeros_like(lmf_data) + mti_data[1:] = lmf_data[1:] - lmf_data[:-1] + + # MTD + # mtd_data = np.fft.fftshift(np.fft.fft(lmf_data, axis=0), axes=0) + window = np.hamming(raw_cmplx.shape[0]).reshape(-1, 1) + mti_windowed = mti_data * window + # MTD: whether to apply fftshift is declared per dataset in dataset_meta.json + # (Syn-RED: false, HiL-RED: true), no longer hard-coded by dataset name + meta = assets.load_dataset_meta(dataset_name) if dataset_name else assets.DEFAULT_META + if meta.get("mtd_fftshift", True): + # Standard pipeline: FFT + fftshift + mtd_data = np.fft.fftshift(np.fft.fft(mti_windowed, axis=0), axes=0) + print(f"[DEBUG] Dataset={dataset_name}: MTD = FFT + fftshift") + else: + # Doppler FFT only, no frequency shift + mtd_data = np.fft.fft(mti_windowed, axis=0) + print(f"[DEBUG] Dataset={dataset_name}: MTD = FFT only (no fftshift)") + + # CFAR + cfar_mask = ca_cfar_2d(mtd_data, guard_cells=(2, 2), training_cells=(4, 4), pfa=1e-4) + print(f"[DEBUG] CFAR detected {np.sum(cfar_mask)} targets") + + return lmf_data, mti_data, mtd_data, cfar_mask + +def ca_cfar_2d(mtd_data, guard_cells=(2, 2), training_cells=(4, 4), pfa=1e-4): + """ + 2D CA-CFAR (Cell Averaging CFAR) detection + + Parameters: + ----------- + mtd_data : ndarray + MTD output data (Doppler x Range) + guard_cells : tuple + Guard cell size (guard_doppler, guard_range) + training_cells : tuple + Training cell size (train_doppler, train_range) + pfa : float + Probability of false alarm + + Returns: + -------- + cfar_mask : ndarray + Binary detection mask + """ + # Convert to amplitude + data = np.abs(mtd_data) + doppler_bins, range_bins = data.shape + + # Compute the CFAR threshold factor + # N = number of training cells + train_doppler, train_range = training_cells + guard_doppler, guard_range = guard_cells + + N = (2 * train_doppler + 2 * guard_doppler + 1) * (2 * train_range + 2 * guard_range + 1) - \ + (2 * guard_doppler + 1) * (2 * guard_range + 1) + + # Threshold factor (OS-CFAR, or the CA-CFAR approximation) + alpha = N * (pfa ** (-1/N) - 1) + + # Initialise the detection mask + cfar_mask = np.zeros_like(data, dtype=bool) + + # Sliding-window loop + for d in range(doppler_bins): + for r in range(range_bins): + # Compute the training-window bounds + d_start = max(0, d - train_doppler - guard_doppler) + d_end = min(doppler_bins, d + train_doppler + guard_doppler + 1) + r_start = max(0, r - train_range - guard_range) + r_end = min(range_bins, r + train_range + guard_range + 1) + + # Extract the window + window = data[d_start:d_end, r_start:r_end].copy() + + # Remove the guard cells (centre region) + gd_start = max(0, d - guard_doppler) - d_start + gd_end = min(doppler_bins, d + guard_doppler + 1) - d_start + gr_start = max(0, r - guard_range) - r_start + gr_end = min(range_bins, r + guard_range + 1) - r_start + + if gd_end > gd_start and gr_end > gr_start: + window[gd_start:gd_end, gr_start:gr_end] = 0 + + # Mean of the training cells + train_sum = np.sum(window) + train_count = np.count_nonzero(window) + + if train_count > 0: + threshold = alpha * train_sum / train_count + + # Detection + if data[d, r] > threshold: + cfar_mask[d, r] = True + + return cfar_mask + + +def os_cfar_2d(mtd_data, guard_cells=(2, 2), training_cells=(4, 4), rank=0.75, pfa=1e-4): + """ + 2D OS-CFAR (Ordered Statistic CFAR) detection - more robust in multi-target environments + + Parameters: + ----------- + mtd_data : ndarray + MTD output data + guard_cells : tuple + Guard cell size + training_cells : tuple + Training cell size + rank : float + Rank of the order statistic (0-1), defaults to the 75th percentile + pfa : float + Probability of false alarm + + Returns: + -------- + cfar_mask : ndarray + Binary detection mask + """ + data = np.abs(mtd_data) + doppler_bins, range_bins = data.shape + + train_doppler, train_range = training_cells + guard_doppler, guard_range = guard_cells + + cfar_mask = np.zeros_like(data, dtype=bool) + + for d in range(doppler_bins): + for r in range(range_bins): + # Extract the training cells + d_start = max(0, d - train_doppler - guard_doppler) + d_end = min(doppler_bins, d + train_doppler + guard_doppler + 1) + r_start = max(0, r - train_range - guard_range) + r_end = min(range_bins, r + train_range + guard_range + 1) + + window = data[d_start:d_end, r_start:r_end].copy() + + # Remove the guard cells and the CUT (cell under test) + gd_start = max(0, d - guard_doppler) - d_start + gd_end = min(doppler_bins, d + guard_doppler + 1) - d_start + gr_start = max(0, r - guard_range) - r_start + gr_end = min(range_bins, r + guard_range + 1) - r_start + + if gd_end > gd_start and gr_end > gr_start: + window[gd_start:gd_end, gr_start:gr_end] = np.nan + + # Collect the training-cell values (excluding nan) + train_values = window[~np.isnan(window)] + + if len(train_values) > 0: + # Sort and pick the value at the requested rank + sorted_values = np.sort(train_values) + k = int(rank * len(sorted_values)) + threshold = sorted_values[min(k, len(sorted_values)-1)] + + # OS-CFAR threshold adjustment + N = len(train_values) + alpha = N * (pfa ** (-1/N) - 1) + threshold = alpha * threshold + + if data[d, r] > threshold: + cfar_mask[d, r] = True + + return cfar_mask + +# ==================== Visualization ==================== +def create_figure_no_colorbar(data, title, cmap='viridis', mask_mode=False, n_classes=2): + """Create a figure without a colorbar, using the predefined SEG_COLORS""" + fig, ax = plt.subplots(figsize=(10, 4), facecolor=COLORS['background']) + ax.set_facecolor(COLORS['background']) + + vmin, vmax = np.percentile(data, (1, 99)) + + if mask_mode and n_classes <= 9: + # Use the predefined SEG_COLORS so colours stay consistent + if n_classes == 2: + hex_colors = SEG_COLORS_2 + else: + hex_colors = SEG_COLORS_9[:n_classes] + + # Convert hex to RGB in [0,1] + colors = [mcolors.to_rgb(c) for c in hex_colors] + + cmap_obj = ListedColormap(colors) + im = ax.imshow(data, cmap=cmap_obj, aspect='auto', vmin=0, vmax=n_classes-1, interpolation='none') + else: + # Non-mask data uses viridis + im = ax.imshow(data, cmap='viridis', aspect='auto', interpolation='nearest', vmin=vmin, vmax=vmax) + + ax.set_title(title, fontsize=10, color=COLORS['secondary'], fontweight='600', pad=8) + ax.tick_params(axis='both', labelsize=7, colors=COLORS['text_dim']) + + for spine in ax.spines.values(): + spine.set_color(COLORS['border']) + spine.set_linewidth(0.5) + + plt.tight_layout() + return fig + + +def create_overlay_figure(echmo_mask, cfar_mask, alpha=0.5, n_classes=2, scan_x=None, + state_label=None, label_color=None, label_opacity=1.0): + """Build the EChMo vs CFAR overlay figure - interactive, via Plotly + + Args: + scan_x: scan-line position (0-range_cells), None means do not draw it + state_label: text shown in the corner ('CFAR detection' / 'EchMo prediction'); + derived from alpha when not given + label_color: colour of that label; derived from state_label when not given + label_opacity: 1.0 right after a switch, dimmed while a result is held + """ + # Local plotly import (pandas is pre-loaded at module level) + import plotly.graph_objs as go + + # Make sure the mask is a 2D numpy array + if echmo_mask.ndim == 3: + echmo_mask = echmo_mask[0] if echmo_mask.shape[0] == 1 else echmo_mask.argmax(axis=0) + if cfar_mask.ndim == 3: + cfar_mask = cfar_mask[0] + + # Cast to a numpy array + echmo_mask = np.asarray(echmo_mask, dtype=np.float32) + cfar_mask = np.asarray(cfar_mask, dtype=bool) + doppler_cells, range_cells = echmo_mask.shape + + fig = go.Figure() + + # Colour configuration + if n_classes == 2: + hex_colors = SEG_COLORS_2 + else: + hex_colors = SEG_COLORS_9[:n_classes] + + # 1. Solid backdrop plus the CFAR detections as round markers. + # The backdrop keeps this panel looking like the other mask panels, and the + # detections are circles in screen space so a single-cell detection stays + # visible without being inflated into a square blob. + fig.add_shape( + type='rect', xref='paper', yref='paper', x0=0, y0=0, x1=1, y1=1, + fillcolor=SEG_COLORS_2[0], line=dict(width=0), layer='below' + ) + + cfar_y, cfar_x = np.where(cfar_mask) + fig.add_trace(go.Scatter( + x=cfar_x.tolist(), + y=cfar_y.tolist(), + mode='markers', + marker=dict( + symbol='circle', + size=3.5, + color='#45CA77' # same colour the legend uses for CFAR targets + ), + marker_opacity=float(min(1.0, max(0.0, 1.0 - alpha))), # visible while CFAR is shown + hoverinfo='skip', + name='CFAR Detection' + )) + + # 2. EchMo layer - colour-mapped (on top, with opacity) + # zmin/zmax are pinned to the full class range so every class keeps the + # colour the legend shows for it. Without them Plotly stretches the + # colorscale over the classes present in *this* frame: a HiL-RED frame + # holding only classes 1 and 6 painted Target with the background colour. + z_echmo = echmo_mask.astype(np.float32).tolist() + colorscale_echmo = [[float(i)/(n_classes-1), hex_colors[i]] for i in range(n_classes)] + + fig.add_trace(go.Heatmap( + z=z_echmo, + colorscale=colorscale_echmo, + showscale=False, + opacity=alpha, + zmin=0, + zmax=n_classes - 1, + hoverinfo='skip', + name='EchMo Prediction' + )) + + # 3. Scan line effect (shown during the transition) + if scan_x is not None: + fig.add_vline( + x=scan_x, + line=dict(color='#00ccff', width=3, dash='solid'), + opacity=0.9 + ) + # Add a glow (wider translucent line) + fig.add_vline( + x=scan_x, + line=dict(color='#00ccff', width=12), + opacity=0.3 + ) + + # 4. State label - says which of the two results is currently displayed + if state_label is None: + if alpha >= 0.5: + state_label, label_color = 'EchMo prediction', '#FDE725' + else: + state_label, label_color = 'CFAR detection', '#45CA77' + if label_color is None: + label_color = '#FDE725' if state_label.startswith('EchMo') else '#45CA77' + if label_opacity > 0.02: + # Plain text, no frame - it is meant as a subtle cue, not a badge + fig.add_annotation( + text=state_label, + xref='paper', yref='paper', + x=0.015, y=0.035, xanchor='left', yanchor='bottom', + showarrow=False, + font=dict(size=13, color=label_color, family='Inter, sans-serif'), + opacity=label_opacity + ) + + # Set up the axes + range_step = max(1, range_cells // 8) + doppler_step = max(1, doppler_cells // 6) + range_ticks = list(range(0, range_cells, range_step)) + doppler_ticks = list(range(0, doppler_cells, doppler_step)) + + fig.update_layout( + # title removed - using HTML header instead + xaxis=dict( + title=dict(text='Range cell', font=dict(size=11, color='#ffffff')), + tickmode='array', + tickvals=range_ticks, + ticktext=[str(i) for i in range_ticks], + tickfont=dict(size=9, color='#ffffff'), + # No grid, exactly like every other mask panel: on the flat CFAR + # backdrop the faint grid lines were the only thing standing out. + showgrid=False, + zeroline=False, + # Pin the range to the data extent. Plotly otherwise pads the range to + # fit the CFAR markers, which pushed the image ~29 px in from the left + # edge (an empty band below range cell 0 with no tick labels) whenever + # detections sat near the range limits -> e.g. HiL-RED deceptive sets. + range=[-0.5, range_cells - 0.5] + ), + yaxis=dict( + title=dict(text='Doppler cell', font=dict(size=11, color='#ffffff')), + tickmode='array', + tickvals=doppler_ticks, + ticktext=[str(i) for i in doppler_ticks], + tickfont=dict(size=9, color='#ffffff'), + showgrid=False, + zeroline=False, + # Reversed (row 0 on top), same as the other mask panels + range=[doppler_cells - 0.5, -0.5] + ), + plot_bgcolor='rgba(0,0,0,0)', + paper_bgcolor='rgba(0,0,0,0)', + # Same box and margins as every other panel (see arr2plot), so the image + # area of this one is pixel-identical to the Ground Truth panel next to + # it - otherwise the same mask is drawn at a different scale. + margin=dict(l=0, r=0, t=0, b=10), + height=280, + # Enable interaction + dragmode='zoom', + selectdirection='any' + ) + + return fig + + +# ==================== Overlay animation (EchMo vs CFAR) ==================== +# The overlay panel alternates between the two results on a 3 s cycle and the +# timer ticks every 0.05 s, so a phase advances in 60 steps of OVERLAY_STEP. +OVERLAY_STEP = 0.01667 # phase advance per tick +OVERLAY_HOLD_SECONDS = 1.0 # how long a clicked result stays pinned on screen +OVERLAY_SWEEP_START = 0.433 # phase where the sweep towards EchMo starts +OVERLAY_ECHMO_START = 0.500 # phase where the EchMo hold starts +OVERLAY_CFAR_START = 0.933 # phase where the sweep back to CFAR starts +OVERLAY_SWEEP_WIDTH = OVERLAY_ECHMO_START - OVERLAY_SWEEP_START + + +def overlay_phase_value(alpha, default=0.0): + """Normalise an animation phase into [0, 1).""" + try: + return float(alpha) % 1.0 + except (TypeError, ValueError): + return default + + +def overlay_manual_pair(manual): + """Normalise the pinned-result state into (layer, deadline). + + Layer is -1 while nothing is pinned, 0 for CFAR and 1 for EchMo. + """ + if isinstance(manual, (tuple, list)) and len(manual) == 2: + try: + return int(manual[0]), float(manual[1]) + except (TypeError, ValueError): + pass + return -1, 0.0 + + +def overlay_range_cells(echmo_mask): + """Number of range cells of a (possibly batched) segmentation mask.""" + mask = echmo_mask + if mask.ndim == 3: + mask = mask[0] if mask.shape[0] == 1 else mask.argmax(axis=0) + return int(mask.shape[1]) + + +def overlay_phase_for_layer(layer): + """Phase that starts the hold of the given layer (0 = CFAR, 1 = EchMo).""" + return OVERLAY_ECHMO_START if layer else 0.0 + + +def overlay_scan_state(alpha, range_cells): + """Describe one frame of the animation. + + Phase map of the 3 s cycle (60 steps of 0.05 s): + 0.000-0.433 (0.0-1.3 s): CFAR hold + 0.433-0.500 (1.3-1.5 s): sweep towards EchMo, left to right + 0.500-0.933 (1.5-2.8 s): EchMo hold + 0.933-1.000 (2.8-3.0 s): sweep back to CFAR, right to left + + Returns the EchMo layer opacity, the scan-line position, how far the current + hold has progressed, which layer the viewer sees and which layer the state + label announces. + """ + if alpha < OVERLAY_SWEEP_START: + return {'layer_alpha': 0.0, 'scan_x': None, 'since_switch': alpha, + 'layer': 0, 'label_layer': 0} + if alpha < OVERLAY_ECHMO_START: + t = (alpha - OVERLAY_SWEEP_START) / OVERLAY_SWEEP_WIDTH + return {'layer_alpha': t, 'scan_x': t * range_cells, 'since_switch': 0.0, + 'layer': 1 if t >= 0.5 else 0, 'label_layer': 1} + if alpha < OVERLAY_CFAR_START: + return {'layer_alpha': 1.0, 'scan_x': None, + 'since_switch': alpha - OVERLAY_ECHMO_START, + 'layer': 1, 'label_layer': 1} + t = (alpha - OVERLAY_CFAR_START) / OVERLAY_SWEEP_WIDTH + return {'layer_alpha': 1.0 - t, 'scan_x': (1.0 - t) * range_cells, + 'since_switch': 0.0, 'layer': 1 if t < 0.5 else 0, 'label_layer': 0} + + +def overlay_label_opacity(since_switch): + """Label brightness: full at the switch, gone 0.26 into a hold phase.""" + if since_switch <= 0.05: + return 1.0 + if since_switch >= 0.26: + return 0.0 + return 1.0 - (since_switch - 0.05) / 0.21 + + +def overlay_layer_label(layer): + """Text and colour of the state label (0 = CFAR, 1 = EchMo).""" + if layer: + return 'EchMo prediction', '#FDE725' + return 'CFAR detection', '#45CA77' + + +def overlay_frame(alpha, echmo_mask, cfar_mask, n_classes, manual=None, now=None): + """Build one frame of the animated overlay (timer callback). + + `manual` is the (layer, deadline) pair written by `overlay_flip`. While that + deadline is in the future the clicked result stays on screen and its phase is + re-asserted on every tick, so a tick that was still in flight when the user + clicked can never undo the click. + + Returns (figure, next_phase). + """ + if echmo_mask is None or cfar_mask is None: + return go.Figure(), overlay_phase_value(alpha) + if now is None: + now = time.monotonic() + range_cells = overlay_range_cells(echmo_mask) + layer, deadline = overlay_manual_pair(manual) + + if layer >= 0 and now < deadline: + phase = overlay_phase_for_layer(layer) + frame = overlay_scan_state(phase, range_cells) + label, color = overlay_layer_label(layer) + fig = create_overlay_figure( + echmo_mask, cfar_mask, alpha=frame['layer_alpha'], n_classes=n_classes, + state_label=label, label_color=color, label_opacity=1.0 + ) + return fig, phase + + phase = overlay_phase_value(alpha) + frame = overlay_scan_state(phase, range_cells) + label, color = overlay_layer_label(frame['label_layer']) + fig = create_overlay_figure( + echmo_mask, cfar_mask, alpha=frame['layer_alpha'], n_classes=n_classes, + scan_x=frame['scan_x'], state_label=label, label_color=color, + label_opacity=overlay_label_opacity(frame['since_switch']) + ) + return fig, (phase + OVERLAY_STEP) % 1.0 + + +def overlay_flip(alpha, now=None): + """Show the result that is not on the screen right now (panel click). + + Returns (figure, phase, manual). `phase` is the hold phase of the clicked + result, so the animation simply continues from there, and `manual` pins that + result for OVERLAY_HOLD_SECONDS. The figure is None while no run has produced + an overlay yet. + """ + phase = overlay_phase_value(alpha) + echmo_mask = _global_results.get('seg_data') + cfar_mask = _global_results.get('cfar_mask') + if echmo_mask is None or cfar_mask is None: + return None, phase, (-1, 0.0) + + seen = overlay_scan_state(phase, overlay_range_cells(echmo_mask))['layer'] + layer = 1 - seen # the result that is currently hidden + if now is None: + now = time.monotonic() + label, color = overlay_layer_label(layer) + fig = create_overlay_figure( + echmo_mask, cfar_mask, alpha=float(layer), + n_classes=_global_results.get('seg_n_classes', 2), + state_label=label, label_color=color, label_opacity=1.0 + ) + return fig, overlay_phase_for_layer(layer), (layer, now + OVERLAY_HOLD_SECONDS) + + +def fig_to_pil(fig): + """Convert a matplotlib figure to a PIL Image""" + buf = io.BytesIO() + fig.savefig(buf, format='png', facecolor=fig.get_facecolor(), + edgecolor='none', bbox_inches='tight', dpi=100) + buf.seek(0) + img = Image.open(buf) + plt.close(fig) + return img + + +def tensor_to_numpy(tensor): + if isinstance(tensor, torch.Tensor): + return tensor.detach().cpu().numpy() + return tensor + + +# ==================== Model Loading ==================== +def load_model(dataset_name, model_type=DEFAULT_MODEL): + """ + Load model based on dataset name and model type. + + Args: + dataset_name: Dataset folder name, discovered from datasets/ (e.g. 'Syn-RED') + model_type: Type of model to load (default: 'echmo') + + Returns: + model: Loaded PyTorch model + cfg: Model configuration dictionary + """ + runs = assets.discover_runs(dataset_name) + if not runs: + raise ValueError( + f"No model runs found for dataset '{dataset_name}'. " + f"Available datasets: {assets.available_datasets()}" + ) + + if model_type not in runs: + raise ValueError( + f"Model type '{model_type}' not found for dataset '{dataset_name}'. " + f"Available: {sorted(runs)}" + ) + + # Model folder/filename discovered from models//*/config.json + model_folder, model_filename = runs[model_type] + + # Construct paths + model_path = assets.run_weights_path(dataset_name, model_folder, model_filename) + config_path = assets.run_config_path(dataset_name, model_folder) + dataset_path = assets.dataset_dir(dataset_name) + + if not os.path.exists(model_path): + raise FileNotFoundError(f"Model file not found: {model_path}") + + if not os.path.exists(config_path): + raise FileNotFoundError(f"Config file not found: {config_path}") + + # utf-8-sig tolerates a BOM in the config file + with open(config_path, 'r', encoding='utf-8-sig') as f: + cfg = json.load(f) + + class EchMo_CFG: + def __init__(self): + self.task_name = 'Segmentation' + + model_cfg = EchMo_CFG() + model_cfg.task_name = cfg.get('task_name', 'Segmentation') + model_cfg.coef_path = 'coefs' + model_cfg.dataset_path = dataset_path + model_cfg.n_pulse = cfg['w_size'] + model_cfg.n_range = cfg['h_size'] + model_cfg.n_classes = cfg['nb_classes'] + model_cfg.n_frames = cfg['nb_input_channels'] + model_cfg.scale = cfg['norm_type'] + model_cfg.lmf_chains = cfg['lmf_chains'] + model_cfg.lmf_channels = cfg['lmf_channels'] + model_cfg.lmf_layers = cfg['lmf_layers'] + model_cfg.lmf_coefs = cfg['lmf_coefs'] + model_cfg.ldc_channels = cfg['ldc_channels'] + model_cfg.ldc_orders = cfg['ldc_orders'] + model_cfg.df_channels = cfg['nb_doppler'] + model_cfg.activation = cfg['activation'] + model_cfg.bias = cfg['bias'] + model_cfg.df_groups = cfg['ldc_orders'] + + model = EchMo(model_cfg) + + if os.path.exists(model_path): + state_dict = torch.load(model_path, map_location=DEVICE) + new_state_dict = OrderedDict() + for k, v in state_dict.items(): + name = k[7:] if k.startswith('module.') else k + new_state_dict[name] = v + model.load_state_dict(new_state_dict, strict=False) + + model.to(DEVICE) + model.eval() + return model, cfg + + +def load_comparison_models(dataset_name): + """ + Load all 6 models for comparison. + Returns a dict of {model_name: (model, config)} + """ + models_dict = {} + + model_configs = { + 'echmo': {'class': EchMo, 'extra_args': True}, + 'unet': {'class': UNet, 'extra_args': False}, + 'deeplabv3plus': {'class': DeepLabV3Plus_Res101, 'extra_args': False}, + 'fcn8s': {'class': FCN8s, 'extra_args': False}, + 'tmva_net_sv': {'class': TMVANet_SV, 'extra_args': True}, + 'vit': {'class': ViT, 'extra_args': False}, + } + + for model_name, (folder, filename) in assets.discover_runs(dataset_name).items(): + config_path = assets.run_config_path(dataset_name, folder) + model_path = assets.run_weights_path(dataset_name, folder, filename) + + if not os.path.exists(config_path) or not os.path.exists(model_path): + print(f"Warning: {model_name} model not found, skipping...") + continue + + with open(config_path, 'r', encoding='utf-8-sig') as f: + cfg = json.load(f) + + # Create model instance + model_cfg = model_configs[model_name] + if model_name == 'echmo': + class EchMo_CFG: + pass + m_cfg = EchMo_CFG() + m_cfg.task_name = cfg.get('task_name', 'Segmentation') + m_cfg.coef_path = 'coefs' + m_cfg.dataset_path = assets.dataset_dir(dataset_name) + m_cfg.n_pulse = cfg['w_size'] + m_cfg.n_range = cfg['h_size'] + m_cfg.n_classes = cfg['nb_classes'] + m_cfg.n_frames = cfg['nb_input_channels'] + m_cfg.scale = cfg['norm_type'] + m_cfg.lmf_chains = cfg['lmf_chains'] + m_cfg.lmf_channels = cfg['lmf_channels'] + m_cfg.lmf_layers = cfg['lmf_layers'] + m_cfg.lmf_coefs = cfg['lmf_coefs'] + m_cfg.ldc_channels = cfg['ldc_channels'] + m_cfg.ldc_orders = cfg['ldc_orders'] + m_cfg.df_channels = cfg['nb_doppler'] + m_cfg.activation = cfg['activation'] + m_cfg.bias = cfg['bias'] + m_cfg.df_groups = cfg['ldc_orders'] + model = model_cfg['class'](m_cfg) + elif model_name == 'tmva_net_sv': + model = model_cfg['class']( + n_classes=cfg['nb_classes'], + n_frames=1, # Use single frame + in_ch=1, + w=cfg['w_size'], + h=cfg['h_size'] + ) + elif model_name == 'vit': + model = model_cfg['class']( + n_classes=cfg['nb_classes'], + in_chans=1 # Use single channel + ) + else: + # UNet, DeepLabV3Plus, FCN8s - use n_frames=1 + model = model_cfg['class']( + n_classes=cfg['nb_classes'], + n_frames=1 # Use single frame + ) + + # Load weights + state_dict = torch.load(model_path, map_location=DEVICE) + new_state_dict = OrderedDict() + for k, v in state_dict.items(): + name = k[7:] if k.startswith('module.') else k + new_state_dict[name] = v + model.load_state_dict(new_state_dict, strict=False) + model.to(DEVICE) + model.eval() + + models_dict[model_name] = (model, cfg) + + return models_dict + + +def arr2plot(arr, colorscale='Viridis', is_mask=False, title=None, n_classes=2): + """Create Plotly figure with axis labels - Fixed: Category to Color binding""" + if arr is None: + return go.Figure() + if hasattr(arr, 'size') and arr.size == 0: + return go.Figure() + if is_mask and arr.ndim == 3: + arr = arr[0] if arr.shape[0] == 1 else arr.argmax(axis=0) + + # Get array dimensions (Doppler cells, Range cells) + if arr.ndim >= 2: + doppler_cells, range_cells = arr.shape + else: + doppler_cells, range_cells = arr.shape[0], 1 + + if is_mask: + # Fixed: Category number = Color list index + if n_classes == 2: + color_list = SEG_COLORS_2 + else: + color_list = SEG_COLORS_9 + + # Build Plotly discrete color scale + colorscale = [] + for class_idx in range(n_classes): + hex_color = color_list[min(class_idx, len(color_list)-1)] + r = int(hex_color[1:3], 16) + g = int(hex_color[3:5], 16) + b = int(hex_color[5:7], 16) + rgb_str = f"rgb({r},{g},{b})" + + colorscale.append([class_idx / n_classes, rgb_str]) + colorscale.append([(class_idx + 1) / n_classes, rgb_str]) + + fig = go.Figure(go.Heatmap( + z=arr, + colorscale=colorscale, + showscale=False, + zmin=0, + zmax=n_classes - 1, + coloraxis=None + )) + else: + fig = go.Figure(go.Heatmap(z=arr, colorscale='Viridis', showscale=False)) + + # Axis styling + range_step = max(1, range_cells // 8) + doppler_step = max(1, doppler_cells // 6) + range_ticks = list(range(0, range_cells, range_step)) + doppler_ticks = list(range(0, doppler_cells, doppler_step)) + + fig.update_layout( + margin=dict(l=0, r=0, t=20 if title else 0, b=10), + xaxis_showgrid=False, + yaxis_showgrid=False, + xaxis=dict( + title=dict(text='Range cell', font=dict(size=11, color='#ffffff')), + showticklabels=True, + tickmode='array', + tickvals=range_ticks, + ticktext=[str(i) for i in range_ticks], + tickfont=dict(size=9, color='#ffffff'), + side='bottom' + ), + yaxis=dict( + title=dict(text='Doppler cell', font=dict(size=11, color='#ffffff')), + showticklabels=True, + tickmode='array', + tickvals=doppler_ticks, + ticktext=[str(i) for i in doppler_ticks], + tickfont=dict(size=9, color='#ffffff'), + autorange='reversed' + ), + height=280, + paper_bgcolor='rgba(0,0,0,0)', + plot_bgcolor='rgba(0,0,0,0)' + ) + + if title: + fig.update_layout( + title=dict( + text=title, + font=dict(size=12, color='#FFC40E'), + x=0.5, + xanchor='center' + ) + ) + + return fig + + +# ==================== 3D View Support ==================== +class ChartViewCache: + """Track the 2D/3D view state of every chart""" + def __init__(self): + self._view_states = {} # {chart_key: '2d'|'3d'} + self._data_cache = {} # {chart_key: numpy_array} + + def get_view_mode(self, chart_key): + """Get the view mode of a chart, defaulting to 2d""" + return self._view_states.get(chart_key, '2d') + + def set_view_mode(self, chart_key, mode): + """Set the view mode of a chart""" + self._view_states[chart_key] = mode + + def cache_data(self, chart_key, data): + """Cache the raw chart data""" + if data is not None: + self._data_cache[chart_key] = data + + def get_data(self, chart_key): + """Get the cached raw data""" + return self._data_cache.get(chart_key) + + def toggle_view(self, chart_key): + """Toggle the view mode and return the new mode""" + current = self.get_view_mode(chart_key) + new_mode = '3d' if current == '2d' else '2d' + self.set_view_mode(chart_key, new_mode) + return new_mode + + def clear(self): + """Clear all caches""" + self._view_states.clear() + self._data_cache.clear() + + +# Global view-cache instance +_view_cache = ChartViewCache() + + +def arr2plot_3d(arr, title=None, colorscale='Viridis'): + """Create 3D Surface plot for radar data - Fixed for Plotly API""" + try: + if arr is None: + return go.Figure() + if hasattr(arr, 'size') and arr.size == 0: + return go.Figure() + + # Ensure 2D array + if arr.ndim > 2: + arr = arr[0] if arr.shape[0] == 1 else arr.mean(axis=0) + + # Ensure array is at least 2D + if arr.ndim < 2: + arr = arr.reshape(1, -1) + + # Get dimensions + doppler_cells, range_cells = arr.shape + + # Create coordinate grids for proper axis labeling + x_coords = np.arange(range_cells) + y_coords = np.arange(doppler_cells) + + # Create surface plot with explicit coordinates + fig = go.Figure(data=[go.Surface( + x=x_coords, + y=y_coords, + z=arr, + colorscale=colorscale, + showscale=False, + hovertemplate='Range: %{x}
Doppler: %{y}
Amplitude: %{z:.4f}', + contours={ + 'x': {'show': False}, + 'y': {'show': False}, + 'z': {'show': False} + } + )]) + + # Calculate tick values + range_step = max(1, range_cells // 6) + doppler_step = max(1, doppler_cells // 6) + + # Fixed: Use correct Plotly API - title=dict(text=..., font=dict(...)) + fig.update_layout( + margin=dict(l=0, r=0, t=40 if title else 10, b=0), + scene=dict( + xaxis=dict( + title=dict(text='Range cell', font=dict(size=10, color='#ffffff')), + tickfont=dict(size=9, color='#ffffff'), + tickmode='linear', + dtick=range_step, + gridcolor='rgba(255,255,255,0.1)', + showbackground=False + ), + yaxis=dict( + title=dict(text='Doppler cell', font=dict(size=10, color='#ffffff')), + tickfont=dict(size=9, color='#ffffff'), + tickmode='linear', + dtick=doppler_step, + gridcolor='rgba(255,255,255,0.1)', + showbackground=False, + autorange='reversed' + ), + zaxis=dict( + title=dict(text='Amplitude', font=dict(size=10, color='#ffffff')), + tickfont=dict(size=9, color='#ffffff'), + gridcolor='rgba(255,255,255,0.1)', + showbackground=False + ), + bgcolor='rgba(26,10,46,0.3)', + camera=dict( + eye=dict(x=1.5, y=1.5, z=1.2) + ) + ), + paper_bgcolor='rgba(0,0,0,0)', + plot_bgcolor='rgba(0,0,0,0)', + height=280, + showlegend=False + ) + + if title: + fig.update_layout( + title=dict( + text=title, + font=dict(size=12, color='#FFC40E'), + x=0.5, + xanchor='center' + ) + ) + + return fig + except Exception as e: + print(f"Error in arr2plot_3d: {e}") + import traceback + traceback.print_exc() + return go.Figure() + + +def arr2plot_3d_optimized(arr, title=None, colorscale='Viridis', zmin=None, zmax=None): + """Create 3D Surface plot with optimized visuals - v2""" + try: + if arr is None: + return go.Figure() + if hasattr(arr, 'size') and arr.size == 0: + return go.Figure() + + # Ensure 2D array + if arr.ndim > 2: + arr = arr[0] if arr.shape[0] == 1 else arr.mean(axis=0) + if arr.ndim < 2: + arr = arr.reshape(1, -1) + + doppler_cells, range_cells = arr.shape + x_coords = np.arange(range_cells) + y_coords = np.arange(doppler_cells) + + # Z range for consistent scaling + if zmin is None: + zmin = np.percentile(arr, 0) + if zmax is None: + zmax = np.percentile(arr, 100) + + # Surface with lighting + fig = go.Figure(data=[go.Surface( + x=x_coords, + y=y_coords, + z=arr, + colorscale=colorscale, + showscale=False, + cmin=zmin, + cmax=zmax, + hovertemplate='Range:%{x}
Doppler:%{y}
Amp:%{z:.3f}', + lighting=dict(ambient=0.6, diffuse=0.7, specular=0.8, roughness=0.4), + lightposition=dict(x=100, y=100, z=200) + )]) + + range_step = max(1, range_cells // 5) + doppler_step = max(1, doppler_cells // 5) + + # MATLAB default view: azimuth=-37.5°, elevation=30° + camera_30deg = dict(eye=dict(x=2.0, y=-2.8, z=2.0), up=dict(x=0, y=0, z=1)) + + fig.update_layout( + margin=dict(l=0, r=0, t=25 if title else 0, b=0), + scene=dict( + xaxis=dict( + title=dict(text='Range', font=dict(size=9, color='rgba(255,255,255,0.6)')), + tickfont=dict(size=8, color='rgba(255,255,255,0.5)'), + tickmode='linear', dtick=range_step, + gridcolor='rgba(255,255,255,0.06)', gridwidth=1, + showbackground=False, zeroline=False, + showline=True, linecolor='rgba(255,255,255,0.12)', linewidth=1 + ), + yaxis=dict( + title=dict(text='Doppler', font=dict(size=9, color='rgba(255,255,255,0.6)')), + tickfont=dict(size=8, color='rgba(255,255,255,0.5)'), + tickmode='linear', dtick=doppler_step, + gridcolor='rgba(255,255,255,0.06)', gridwidth=1, + showbackground=False, zeroline=False, autorange='reversed', + showline=True, linecolor='rgba(255,255,255,0.12)', linewidth=1 + ), + zaxis=dict( + title=dict(text='Amp', font=dict(size=9, color='rgba(255,255,255,0.6)')), + tickfont=dict(size=8, color='rgba(255,255,255,0.5)'), + gridcolor='rgba(255,255,255,0.06)', gridwidth=1, + showbackground=False, zeroline=False, + showline=True, linecolor='rgba(255,255,255,0.12)', linewidth=1, + range=[zmin, zmax], nticks=5 + ), + bgcolor='rgba(0,0,0,0)', + camera=camera_30deg, + # Inner aspect ratio matches the canvas, 2.5:1 + aspectmode='manual', + aspectratio=dict(x=2.5, y=1.0, z=0.5) + ), + # paper_bgcolor='#1a0a2e', + # plot_bgcolor='#1a0a2e', + paper_bgcolor='rgba(0,0,0,0)', + plot_bgcolor='rgba(0,0,0,0)', + autosize=False, + width=500, + height=500 + ) + + if title: + fig.update_layout(title=dict(text=title, font=dict(size=11, color='#FFC40E'), x=0.5)) + + return fig + except Exception as e: + print(f"Error in arr2plot_3d: {e}") + return go.Figure() + + +def get_plot_for_chart(chart_key, data, title=None, is_mask=False, n_classes=2): + """Build the chart for the current view mode""" + try: + if data is None: + return go.Figure() + + # Cache the raw data + _view_cache.cache_data(chart_key, data) + + # Get the current view mode + view_mode = _view_cache.get_view_mode(chart_key) + + if view_mode == '3d' and not is_mask: + # 3D mode is only for non-mask data - use the optimised variant + return arr2plot_3d_optimized(data, title=title) + else: + # 2D mode (default) + return arr2plot(data, is_mask=is_mask, title=title, n_classes=n_classes) + except Exception as e: + print(f"Error in get_plot_for_chart for {chart_key}: {e}") + import traceback + traceback.print_exc() + return go.Figure() + + +def toggle_chart_view(chart_key, current_data, title=None, is_mask=False, n_classes=2): + """Toggle the chart view mode and return the new figure""" + new_mode = _view_cache.toggle_view(chart_key) + + # Use the passed-in data, otherwise fall back to the cache + data = current_data if current_data is not None else _view_cache.get_data(chart_key) + + if data is None: + return go.Figure(), new_mode + + if new_mode == '3d' and not is_mask: + fig = arr2plot_3d(data, title=title) + else: + fig = arr2plot(data, is_mask=is_mask, title=title, n_classes=n_classes) + + return fig, new_mode + + +def run_comparison_inference(dataset_name, seq_name, frame_name): + """ + Run inference with all models for comparison. + Returns dict with results from all models. + """ + if not dataset_name or not seq_name or not frame_name: + return None, "Please select data source, sequence, and frame." + + # Load echo data + echo_data = load_echo_data(dataset_name, seq_name, frame_name) + if echo_data is None: + return None, "Echo data not found" + + # Load annotation + annotation = load_annotation(dataset_name, seq_name, frame_name) + + # Prepare input for EchMo (complex data) + if echo_data.shape[0] == 2: + real_part = echo_data[0] + imag_part = echo_data[1] + echo_cmplx = real_part + 1j * imag_part + else: + echo_cmplx = echo_data + + x_complex = torch.from_numpy(echo_cmplx).unsqueeze(0).unsqueeze(0).to(DEVICE) + x_complex = torch.complex(x_complex.real.float(), x_complex.imag.float()) + + # Prepare MTD amplitude input for other models. + # The source folder is dataset-specific and declared in dataset_meta.json + # (Syn-RED -> range_doppler_mtdData_amp, HiL-RED -> range_doppler_MTD) + mtd_path = assets.mtd_amp_path(dataset_name, seq_name, frame_name) + if os.path.exists(mtd_path): + mtd_amp = np.abs(np.load(mtd_path)) + else: + # Fallback: compute from echo data + mtd_amp = np.abs(echo_cmplx) + + # Ensure mtd_amp is 2D + if mtd_amp.ndim == 3: + mtd_amp = mtd_amp[0] + + # Load all models + models_dict = load_comparison_models(dataset_name) + + results = {} + n_classes = 2 + + with torch.no_grad(): + for model_name, (model, cfg) in models_dict.items(): + try: + n_classes = cfg.get('nb_classes', 2) + + if model_name == 'echmo': + # EchMo uses complex input + output, _, _, _ = model(x_complex) + elif model_name == 'tmva_net_sv': + # TMVA-Net expects 5D input: (batch, n_frames, in_ch, h, w) + # First expand_dims adds temporal dimension, second adds in_ch dimension + # Then unsqueeze(0) adds batch dimension + x_tmva = np.expand_dims(mtd_amp, axis=0) # (1, h, w) - add temporal dim (n_frames=1) + x_tmva = np.expand_dims(x_tmva, axis=0) # (1, 1, h, w) - add in_ch dim + x_tmva = torch.from_numpy(x_tmva).unsqueeze(0).to(DEVICE).float() # (1, 1, 1, h, w) - add batch dim + output = model(x_tmva) + else: + # Other models (U-Net, DeepLabv3+, FCN-8s, ViT) use single frame + # Input shape: (batch, 1, h, w) + x_other = torch.from_numpy(mtd_amp).unsqueeze(0).unsqueeze(0).to(DEVICE).float() + output = model(x_other) + + pred_mask = torch.argmax(output, dim=1)[0].cpu().numpy() + results[model_name] = pred_mask + except Exception as e: + print(f"Error running {model_name}: {e}") + import traceback + traceback.print_exc() + results[model_name] = None + + # Raw echo amplitude for display + echo_amp = np.abs(echo_cmplx) + if echo_amp.ndim == 3: + echo_amp = echo_amp[0] + + # Ground truth (accepts one-hot and label maps, see annotation_to_label_map) + gt_mask = annotation_to_label_map(annotation) + + return { + 'raw_echo': echo_amp, + 'mtd': mtd_amp, + 'gt_mask': gt_mask, + 'predictions': results, + 'n_classes': n_classes + }, f"✓ Compared {len([r for r in results.values() if r is not None])} models on {dataset_name}/{seq_name}/{frame_name}" + + +# ==================== Data Loading ==================== +# All paths are resolved by asset_paths (the folder layout is defined in one place) +def load_dataset_json(dataset_name): + return assets.load_dataset_index(dataset_name) + +def load_echo_data(dataset_name, seq_name, frame_name): + echo_path = assets.echo_path(dataset_name, seq_name, frame_name) + if os.path.exists(echo_path): + return np.load(echo_path) + return None + +def load_annotation(dataset_name, seq_name, frame_name): + annot_path = assets.annotation_path(dataset_name, seq_name, frame_name) + if os.path.exists(annot_path): + return np.load(annot_path) + return None + +def annotation_to_label_map(annotation): + """ + Normalise an annotation into a 2D label map (Doppler, Range): one class id per pixel. + + Both on-disk layouts are supported, so old and new data just work: + - one-hot (C, Doppler, Range) : all channels sum to 1 per pixel -> argmax + (1, Doppler, Range) : single-channel mask -> drop the leading dim + (1, C, Doppler, Range): one extra leading dim -> drop it and recurse + - label map (Doppler, Range) : already a label map -> returned as-is + + Syn-RED stores one-hot (uint8, C=2); HiL-RED ships + int8 label maps (converted from the original 9-channel float64 one-hot). + """ + if annotation is None: + return None + arr = np.asarray(annotation) + if arr.ndim < 2: + return arr.reshape(1, -1) + if arr.ndim == 2: + return arr # already a label map + if arr.ndim == 3 and arr.shape[0] == 1: + return arr[0] # single-channel mask + if arr.ndim == 3: + return arr.argmax(axis=0) # one-hot (C, D, R) + return annotation_to_label_map(arr[0]) # drop the extra leading dim + +def load_echo_data_from_file(file_path): + """ + Load the echo signal from an uploaded file (.npy) + """ + if file_path is None: + raise ValueError("Please upload an echo signal file") + + file_ext = os.path.splitext(file_path)[1].lower() + + if file_ext != '.npy': + raise ValueError(f"Unsupported echo file format: {file_ext}. Please use .npy format") + + echo_data = np.load(file_path) + print(f"[DEBUG] Loaded echo signal from .npy shape={echo_data.shape}, dtype={echo_data.dtype}") + + if echo_data.ndim not in [2, 3]: + raise ValueError(f"Invalid echo data shape: {echo_data.shape}. Expected 2D or 3D array") + + return echo_data + + +# ==================== Global Variables ==================== +model_cache = {} +_global_results = {} + + +# ==================== Processing Functions ==================== +def process_with_model(model, echo_data): + if echo_data.shape[0] == 2: + real_part = echo_data[0] + imag_part = echo_data[1] + echo_cmplx = real_part + 1j * imag_part + else: + echo_cmplx = echo_data + + x = torch.from_numpy(echo_cmplx).unsqueeze(0).unsqueeze(0).to(DEVICE) + x = torch.complex(x.real.float(), x.imag.float()) + + with torch.no_grad(): + output, lmf_out, mldc_out, gdf_out = model(x) + + return output, lmf_out, mldc_out, gdf_out + + +def run_inference(dataset_name, seq_name, frame_name): + global _global_results + if not dataset_name or not seq_name or not frame_name: + msg = "Please select data source, sequence, and frame." + print("[run_inference]", msg) + return [None] * 10 + [msg, True] # the last value flags whether ground truth exists + + if not assets.discover_runs(dataset_name): + msg = f"Configuration not found for {dataset_name}" + print("[run_inference]", msg) + return [None] * 10 + [msg, True] + + dataset_path = assets.dataset_dir(dataset_name) + if not os.path.exists(dataset_path): + msg = f"Dataset path not found: {dataset_path}" + print("[run_inference]", msg) + return [None] * 10 + [msg, True] + + model_key = dataset_name + if model_key not in model_cache: + try: + model, config = load_model(dataset_name) + model_cache[model_key] = (model, config) + except Exception as e: + msg = f"Error loading model: {str(e)}" + print("[run_inference]", msg) + return [None] * 10 + [msg, True] + + model, config = model_cache[model_key] + n_classes = config.get('nb_classes', 2) + + echo_data = load_echo_data(dataset_name, seq_name, frame_name) + if echo_data is None: + msg = "Echo data not found" + print("[run_inference]", msg) + return [None] * 10 + [msg, True] + + annotation = load_annotation(dataset_name, seq_name, frame_name) + + try: + model_output, lmf_out, mldc_out, gdf_out = process_with_model(model, echo_data) + except Exception as e: + msg = f"Error during model inference: {str(e)}" + print("[run_inference]", msg) + return [None] * 10 + [msg, True] + + # Traditional signal processing + try: + trad_lmf, trad_mti, trad_mtd, trad_cfar = traditional_lmf_mti_mtd( + echo_data, + dataset_name=dataset_name, + dataset_path=dataset_path + ) + except Exception as e: + msg = f"Error during traditional processing: {str(e)}" + print("[run_inference]", msg) + traceback.print_exc() + return [None] * 10 + [msg, True] + + # Raw Echo Input + if echo_data.shape[0] == 2: + echo_amp = np.abs(echo_data[0] + 1j * echo_data[1]) + else: + echo_amp = np.abs(echo_data) + if echo_amp.ndim == 3: + echo_amp = echo_amp[0] + + # EchMo LMF + lmf_batch0 = lmf_out[0] + lmf_amp = tensor_to_numpy(torch.abs(lmf_batch0).mean(dim=0)) + + # Traditional LMF + trad_lmf_amp = np.abs(trad_lmf) + if trad_lmf_amp.ndim == 3: + trad_lmf_amp = trad_lmf_amp[0] + + # EchMo MLDC + mldc_batch0 = mldc_out[0] + mldc_amp = tensor_to_numpy(torch.abs(mldc_batch0).mean(dim=0)) + + # Traditional MTI + trad_mti_amp = np.abs(trad_mti) + if trad_mti_amp.ndim == 3: + trad_mti_amp = trad_mti_amp[0] + + # EchMo GDF + gdf_batch0 = gdf_out[0] + gdf_amp = tensor_to_numpy(torch.abs(gdf_batch0).mean(dim=0)) + + # Traditional MTD + trad_mtd_amp = np.abs(trad_mtd) + if trad_mtd_amp.ndim == 3: + trad_mtd_amp = trad_mtd_amp[0] + + # Segmentation Prediction + pred_mask = tensor_to_numpy(torch.argmax(model_output, dim=1)[0]) + + # Store for curtain comparison + _global_results['seg_data'] = pred_mask + _global_results['seg_n_classes'] = n_classes + _global_results['trad_rd_data'] = trad_mtd_amp + _global_results['cfar_mask'] = trad_cfar + + # Ground Truth (accepts one-hot and label maps, see annotation_to_label_map) + gt_mask = annotation_to_label_map(annotation) + has_gt = annotation is not None + + status_msg = f"✓ Processed: {dataset_name} / {seq_name} / {frame_name}" + if not has_gt: + status_msg += " | Ground truth not found" + + return [ + echo_amp, # 0: raw_input + gt_mask, # 1: ground_truth (after the swap: was pred_mask) + pred_mask, # 2: pred_mask (after the swap: was gt_mask) + lmf_amp, # 3: echmo_lmf + trad_lmf_amp, # 4: trad_lmf + mldc_amp, # 5: echmo_mldc + trad_mti_amp, # 6: trad_mti + gdf_amp, # 7: echmo_gdf + trad_mtd_amp, # 8: trad_mtd + trad_cfar, # 9: cfar_mask (added) + status_msg, # 10: status + has_gt # 11: has_ground_truth flag + ] + + +# NOTE: the "Custom Data" entry has been removed from the UI, so this function +# is currently unreferenced. It is kept so the feature can be re-enabled by +# adding assets.CUSTOM_DATASET back to `all_data_sources` in create_interface(). +def run_inference_custom(tx_signal_file, echo_file, model_name): + """ + Handle the files uploaded by the user (custom mode) + """ + global _global_results + + if tx_signal_file is None or echo_file is None: + msg = "Please upload both transmit signal and echo signal files." + print("[run_inference_custom]", msg) + return [None] * 10 + [msg, False] # custom data has no ground truth + + if not model_name: + msg = "Please select a model." + print("[run_inference_custom]", msg) + return [None] * 10 + [msg, False] + + # Load the transmit signal + try: + tx_signal = load_transmit_signal_from_file(tx_signal_file) + except Exception as e: + msg = f"Error loading transmit signal: {str(e)}" + print("[run_inference_custom]", msg) + return [None] * 10 + [msg, False] + + # Load the echo signal + try: + echo_data = load_echo_data_from_file(echo_file) + except Exception as e: + msg = f"Error loading echo signal: {str(e)}" + print("[run_inference_custom]", msg) + return [None] * 10 + [msg, False] + + # Check model config (note: in custom mode model_name actually means "which dataset's pretrained model") + if not assets.discover_runs(model_name): + msg = f"Configuration not found for {model_name}" + print("[run_inference_custom]", msg) + return [None] * 10 + [msg, False] + + # Load the model + model_key = model_name + if model_key not in model_cache: + try: + model, config = load_model(model_name) + model_cache[model_key] = (model, config) + except Exception as e: + msg = f"Error loading model: {str(e)}" + print("[run_inference_custom]", msg) + return [None] * 10 + [msg, False] + + model, config = model_cache[model_key] + n_classes = config.get('nb_classes', 2) + + # Model inference + try: + model_output, lmf_out, mldc_out, gdf_out = process_with_model(model, echo_data) + except Exception as e: + msg = f"Error during model inference: {str(e)}" + print("[run_inference_custom]", msg) + traceback.print_exc() + return [None] * 10 + [msg, False] + + # Traditional signal processing - fix: capture trad_cfar as the 4th return value + try: + trad_lmf, trad_mti, trad_mtd, trad_cfar = traditional_lmf_mti_mtd( + echo_data, + tx_signal=tx_signal + ) + except Exception as e: + msg = f"Error during traditional processing: {str(e)}" + print("[run_inference_custom]", msg) + traceback.print_exc() + return [None] * 10 + [msg, False] + + # Raw Echo Input + if echo_data.shape[0] == 2: + echo_amp = np.abs(echo_data[0] + 1j * echo_data[1]) + else: + echo_amp = np.abs(echo_data) + if echo_amp.ndim == 3: + echo_amp = echo_amp[0] + + # EchMo LMF + lmf_batch0 = lmf_out[0] + lmf_amp = tensor_to_numpy(torch.abs(lmf_batch0).mean(dim=0)) + + # Traditional LMF + trad_lmf_amp = np.abs(trad_lmf) + if trad_lmf_amp.ndim == 3: + trad_lmf_amp = trad_lmf_amp[0] + + # EchMo MLDC + mldc_batch0 = mldc_out[0] + mldc_amp = tensor_to_numpy(torch.abs(mldc_batch0).mean(dim=0)) + + # Traditional MTI + trad_mti_amp = np.abs(trad_mti) + if trad_mti_amp.ndim == 3: + trad_mti_amp = trad_mti_amp[0] + + # EchMo GDF + gdf_batch0 = gdf_out[0] + gdf_amp = tensor_to_numpy(torch.abs(gdf_batch0).mean(dim=0)) + + # Traditional MTD + trad_mtd_amp = np.abs(trad_mtd) + if trad_mtd_amp.ndim == 3: + trad_mtd_amp = trad_mtd_amp[0] + + # Segmentation Prediction + pred_mask = tensor_to_numpy(torch.argmax(model_output, dim=1)[0]) + + # Store for curtain comparison + _global_results['seg_data'] = pred_mask + _global_results['seg_n_classes'] = n_classes + _global_results['trad_rd_data'] = trad_mtd_amp + _global_results['cfar_mask'] = trad_cfar + + status_msg = f"✓ Processed custom data using model trained on {model_name} | No ground truth available" + + + # NOTE: in Custom mode ground_truth is None; keep the same return order as run_inference + return [ + echo_amp, # 0: raw_input + None, # 1: ground_truth (None for custom data, position after the swap) + pred_mask, # 2: pred_mask (position after the swap) + lmf_amp, # 3: echmo_lmf + trad_lmf_amp, # 4: trad_lmf + mldc_amp, # 5: echmo_mldc + trad_mti_amp, # 6: trad_mti + gdf_amp, # 7: echmo_gdf + trad_mtd_amp, # 8: trad_mtd + trad_cfar, # 9: cfar_mask (added) + status_msg, # 10: status + False # 11: has_ground_truth = False + ] + + +def get_available_datasets(): + """Datasets are discovered from disk (datasets/*/light_dataset_frame_oriented.json)""" + return assets.available_datasets() + +def get_sequences(dataset_name): + return assets.get_sequences(dataset_name) + +def get_frames(dataset_name, seq_name): + return assets.get_frames(dataset_name, seq_name) + + +# ==================== Custom CSS ==================== +CUSTOM_CSS = """ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Exo+2:wght@400;500;600;700&display=swap'); + +.gradio-container { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important; + background: linear-gradient(135deg, #1a0a2e 0%, #2a004f 50%, #0d0618 100%) !important; + color: #e2e8f0 !important; + min-height: 100vh !important; +} + +/* ===== Startup loading animation ===== */ +#loading-screen { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: #1a0a2e; + display: flex !important; + flex-direction: column; + justify-content: center; + align-items: center; + z-index: 2147483647 !important; + transition: opacity 0.5s ease-out; +} + +#loading-screen.hidden { + opacity: 0; + pointer-events: none; +} + +/* Main title - on top */ +.loading-title { + color: #FFC40E; + font-size: 2.2rem; + font-weight: 800; + margin-bottom: 16px; + text-align: center; + letter-spacing: 2px; + font-family: 'Exo 2', sans-serif; + text-shadow: 0 0 20px rgba(255, 196, 14, 0.5), 0 0 40px rgba(255, 196, 14, 0.3); + position: relative; + z-index: 2147483647; +} + +/* Subtitle - on top */ +.loading-subtitle { + color: #c4b5fd; + font-size: 1rem; + font-weight: 400; + margin-bottom: 80px; + text-align: center; + font-family: 'Exo 2', sans-serif; + letter-spacing: 4px; + position: relative; + z-index: 2147483647; +} + +/* Progress bar area - on top */ +.loading-progress-area { + width: 400px; + position: relative; + z-index: 2147483647; +} + +/* Progress bar container - white border */ +.progress-container { + width: 100%; + height: 8px; + background: rgba(0, 0, 0, 0.4); + border: 2px solid rgba(255, 255, 255, 0.5); + border-radius: 10px; + padding: 2px; + box-shadow: + 0 0 20px rgba(124, 58, 237, 0.3), + inset 0 2px 4px rgba(0, 0, 0, 0.5); + position: relative; + z-index: 2147483647; +} + +/* Progress bar fill - gold */ +.progress-bar { + height: 100%; + width: 0%; + background: linear-gradient(90deg, + #f59e0b 0%, + #FFC40E 30%, + #fff5a8 50%, + #FFC40E 70%, + #f59e0b 100% + ); + background-size: 200% 100%; + border-radius: 6px; + box-shadow: + 0 0 10px rgba(255, 196, 14, 0.6), + 0 0 20px rgba(255, 196, 14, 0.3); + position: relative; + z-index: 2147483647; + overflow: hidden; + transition: width 0.1s linear; +} + +/* Progress bar glow pulse */ +@keyframes barGlow { + 0%, 100% { + box-shadow: 0 0 10px rgba(255, 196, 14, 0.6), 0 0 20px rgba(255, 196, 14, 0.3); + } + 50% { + box-shadow: 0 0 20px rgba(255, 196, 14, 0.9), 0 0 40px rgba(255, 196, 14, 0.5); + } +} + +/* Inner shimmer of the progress bar */ +.progress-bar::after { + content: ''; + position: absolute; + top: 0; + left: -50%; + width: 50%; + height: 100%; + background: linear-gradient(90deg, + transparent 0%, + rgba(255, 255, 255, 0.6) 50%, + transparent 100% + ); + animation: shineMove 1.5s ease-in-out infinite; +} + +@keyframes shineMove { + 0% { left: -50%; } + 100% { left: 150%; } +} + +@keyframes barShimmer { + 0% { background-position: 200% 0; } + 100% { background-position: -200% 0; } +} + +/* Status text */ +.loading-status-row { + display: flex; + justify-content: center; + align-items: center; + margin-top: 20px; + gap: 12px; + position: relative; + z-index: 2147483647; +} + +.loading-status { + color: #c4b5fd; + font-size: 0.9rem; + font-family: 'Exo 2', monospace; + letter-spacing: 1px; + text-transform: uppercase; +} + +.loading-percent { + color: #FFC40E; + font-size: 0.9rem; + font-family: 'Exo 2', monospace; + font-weight: 700; + min-width: 40px; + text-align: right; +} + +/* ===== Header with Logo ===== */ +.header-container { + display: flex; + align-items: center; + justify-content: space-between; + padding: 20px 30px 15px; + position: relative; +} + +.header-logo { + width: 150px; + height: 150px; + object-fit: contain; + filter: drop-shadow(0 0 20px rgba(255, 196, 14, 0.5)); + animation: logoFadeIn 1.2s ease-out, logoGlow 3s ease-in-out 1.2s infinite; +} + +@keyframes logoFadeIn { + 0% { + opacity: 0; + transform: scale(0.8) rotate(-10deg); + } + 100% { + opacity: 1; + transform: scale(1) rotate(0deg); + } +} + +@keyframes logoGlow { + 0%, 100% { + filter: drop-shadow(0 0 20px rgba(255, 196, 14, 0.5)); + } + 50% { + filter: drop-shadow(0 0 35px rgba(255, 196, 14, 0.8)); + } +} + +.header-title-wrapper { + text-align: center; + flex: 1; +} + +.header-title { + color: #FFC40E; + font-size: 1.8rem; + font-weight: 700; + letter-spacing: 2px; + line-height: 1.2; + text-align: center; + font-family: 'Exo 2', sans-serif !important; + /* Gradient text effect */ + background: linear-gradient( + 90deg, + #FFC40E 0%, + #fff5a8 25%, + #FFC40E 50%, + #fff5a8 75%, + #FFC40E 100% + ); + background-size: 200% auto; + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + animation: shimmer 3s linear infinite, fadeInDown 1s ease-out; +} + +/* Text shimmer animation */ +@keyframes shimmer { + 0% { background-position: 200% center; } + 100% { background-position: -200% center; } +} + +/* Fade-in falling animation */ +@keyframes fadeInDown { + 0% { + opacity: 0; + transform: translateY(-20px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +/* Subtitle animation */ +.header-subtitle { + animation: fadeInUp 1s ease-out 0.3s both; +} + +@keyframes fadeInUp { + 0% { + opacity: 0; + transform: translateY(10px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +.header-subtitle { + color: #c4b5fd; + font-size: 0.95rem; + font-weight: 400; + margin-top: 6px; + text-align: center; + letter-spacing: 1px; + animation: fadeInUp 1s ease-out 0.5s both, pulse 3s ease-in-out 1.5s infinite; +} + +/* Fade-in rising animation */ +@keyframes fadeInUp { + 0% { + opacity: 0; + transform: translateY(15px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +/* Subtle breathing effect */ +@keyframes pulse { + 0%, 100% { opacity: 0.8; } + 50% { opacity: 1; } +} + +@media (max-width: 768px) { + .header-container { + flex-direction: column; + padding: 15px 20px; + } + .header-logo { + width: 100px; + height: 100px; + margin-bottom: 10px; + } + .header-title { + font-size: 1.4rem; + } +} + +/* ===== Tab button style - tech look ===== */ +.tab-nav { + background: transparent !important; + border-bottom: 1px solid rgba(124, 58, 237, 0.3) !important; + padding: 0 20px !important; +} + +.tab-nav button, +[role="tab"], +.tabs .tab, +.gr-tab, +.gr-tabs button, +button[role="tab"] { + color: #c4b5fd !important; + font-weight: 500 !important; + background: transparent !important; + border: none !important; + padding: 14px 24px !important; + transition: all 0.3s ease !important; + border-radius: 8px 8px 0 0 !important; + font-size: 0.95rem !important; +} + +.tab-nav button:hover, +[role="tab"]:hover, +.tabs .tab:hover, +.gr-tab:hover { + color: #f8fafc !important; + background: rgba(124, 58, 237, 0.15) !important; +} + +.tab-nav button.selected, +[role="tab"][aria-selected="true"], +.tabs .tab.selected, +.gr-tab[aria-selected="true"], +.gr-tabs button[data-bp="selected"], +button[role="tab"][aria-selected="true"] { + color: #FFC40E !important; + font-weight: 600 !important; + background: linear-gradient(180deg, rgba(255, 196, 14, 0.1) 0%, transparent 100%) !important; + border-bottom: 2px solid #FFC40E !important; + box-shadow: 0 -2px 12px rgba(255, 196, 14, 0.15) !important; +} + +/* Deeper nested selectors */ +.gradio-container .tab-nav *, +.gradio-container [class*="tab"] button { + color: #c4b5fd !important; +} + +.gradio-container .tab-nav .selected, +.gradio-container [class*="tab"] [class*="selected"], +.gradio-container [class*="tab"] [aria-selected="true"] { + color: #FFC40E !important; +} + +/* Header */ +.header-title { + text-align: center; + padding: 24px 0 20px; + color: #FFC40E; + font-size: 2.2rem; + font-weight: 700; + letter-spacing: 0.5px; +} + +/* ===== Control row - card style ===== */ +.control-row { + display: flex !important; + align-items: flex-end !important; + background: rgba(45, 27, 78, 0.6) !important; + border: 1px solid rgba(124, 58, 237, 0.3) !important; + border-radius: 12px !important; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.05) !important; + padding: 16px 20px !important; + margin: 0 0 16px 0 !important; + min-height: unset !important; + gap: 16px !important; + overflow: visible !important; + /* Remove backdrop-filter to avoid positioning issues */ +} + +.control-item { + flex: 1; + min-width: 0 !important; + position: relative !important; + overflow: visible !important; +} + +.control-item label { + display: block; + font-size: 0.7rem; + color: #a78bfa; + margin-bottom: 8px; + text-transform: uppercase; + letter-spacing: 0.8px; + font-weight: 500; +} + +/* ===== Dropdown - unify inner and outer layers ===== */ + +/* Outer container - purple border, the overall frame */ +.dark-dropdown { + width: 380px !important; + height: 36px !important; + background: #1a0a2e !important; + border: 1px solid #7c3aed !important; + border-radius: 6px !important; + overflow: hidden !important; + padding: 0 !important; + margin-left: 10px !important; +} + +/* Inner container - fills the outer one */ +.dark-dropdown > div, +.dark-dropdown > div > div { + width: 100% !important; + height: 100% !important; + min-height: 100% !important; + min-width: 100% !important; + background: transparent !important; + border: none !important; + padding: 0 !important; + margin: 0 !important; + box-sizing: border-box !important; +} + +/* Input area - fill the box and drop all borders */ +.dark-dropdown input, +.dark-dropdown [contenteditable], +.dark-dropdown [role="combobox"] { + width: 100% !important; + height: 100% !important; + color: #ffffff !important; + background: transparent !important; + border: none !important; + outline: none !important; + box-shadow: none !important; + padding: 0 8px !important; + margin: 0 !important; + box-sizing: border-box !important; + # min-width: 100% !important; + # max-width: 100% !important; + min-width: 450px !important; /* Min width */ + max-width: 500px !important; /* Max width */ +} + +.dark-dropdown:hover { + border-color: #FFC40E !important; + box-shadow: 0 0 8px rgba(255, 196, 14, 0.4) !important; +} + +/* Inner listbox (input area) - transparent border */ +.dark-dropdown [role="listbox"] { + width: 100% !important; + height: 100% !important; + background: #1a0a2e !important; + border: none !important; + padding: 0 !important; + margin: 0 !important; +} + +/* Dropdown list (in the portal) - natural size, no border */ +[role="listbox"] { + background: rgba(26, 10, 46, 0.05) !important; /* Translucent dark */ + backdrop-filter: blur(10px); + border: none !important; + border-radius: 6px !important; + width: auto !important; + height: auto !important; +} + +/* Hide all processing/loading progress bars */ +[class*="loading"], +[class*="progress"], +[class*="spinner"], +[class*="processing"], +[class*="generating"], +[data-testid*="loader"], +[data-testid*="progress"], +svg[class*="animate"], +[role="status"] { + display: none !important; + visibility: hidden !important; +} + +/* List item */ +[role="listbox"] [role="option"] { + color: #ffffff !important; +} + +/* List item hover */ +[role="listbox"] [role="option"]:hover { + background: #2d1b4e !important; + color: #FFC40E !important; +} + +[role="listbox"] [aria-selected="true"] { + background: rgba(26, 10, 46, 0.55) !important; /* Translucent background */ + color: #FFC40E !important; /* gold text */ +} + +/* ========== Run button - gold ========== */ +.run-btn { + background: linear-gradient(135deg, #FFC40E 0%, #f59e0b 100%) !important; + border: none !important; + color: #1a0a2e !important; + font-weight: 700 !important; + padding: 10px 32px !important; + border-radius: 10px !important; + height: 44px !important; + min-width: 110px !important; + box-shadow: 0 4px 15px rgba(255, 196, 14, 0.4), 0 0 20px rgba(255, 196, 14, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.3) !important; + align-self: flex-end !important; + margin-bottom: 0 !important; + transition: all 0.3s ease !important; + text-transform: uppercase; + letter-spacing: 1px; +} + +.run-btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 25px rgba(255, 196, 14, 0.6), 0 0 30px rgba(255, 196, 14, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3) !important; + filter: brightness(1.15); +} + +.run-btn:active { + transform: translateY(0); +} + +/* ========== Other styles ========== */ +.col-header { + font-size: 1rem !important; + color: #FFC40E !important; + font-weight: 600 !important; + text-transform: uppercase; + letter-spacing: 1px; + text-align: center; + padding: 12px 16px !important; + background: linear-gradient(135deg, rgba(45, 27, 78, 0.6) 0%, rgba(26, 10, 46, 0.6) 100%) !important; + border-radius: 10px !important; + margin-bottom: 12px !important; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.05) !important; + border: 1px solid rgba(124, 58, 237, 0.2) !important; + line-height: 1.2 !important; + backdrop-filter: blur(10px) !important; +} + +.plot-container { + background: transparent !important; + border: none !important; + padding: 0 !important; + margin: 0 !important; +} + +.status-bar { + margin: 20px !important; + padding: 14px 20px !important; + background: linear-gradient(135deg, rgba(45, 27, 78, 0.6) 0%, rgba(26, 10, 46, 0.6) 100%) !important; + color: #f8fafc !important; + border: 1px solid rgba(124, 58, 237, 0.2) !important; + border-radius: 10px !important; + font-size: 0.9rem !important; + font-family: monospace !important; + font-weight: 500 !important; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.05) !important; + backdrop-filter: blur(10px) !important; +} + +.status-bar > div, +.status-bar > div > div, +.status-bar textarea, +.status-bar input { + background: transparent !important; + color: #ffffff !important; + border: none !important; + box-shadow: none !important; +} + +.model-selector { + background: #181826 !important; + border: 1px solid #232345 !important; + border-radius: 4px !important; +} + +.dynamic-label { + font-size: 0.7rem; + color: #ffffff; + margin-bottom: 6px; + text-transform: uppercase; + letter-spacing: 0.5px; + display: block; + transition: all 0.3s ease; +} + +@media (max-width: 1100px) { + .control-row { + flex-wrap: wrap !important; + } + + .control-item { + min-width: 200px !important; + } +} + +/* ===== 3D View System - Floating Toggle Buttons ===== */ + +/* Chart container with relative positioning for absolute toggle */ +.chart-with-toggle { + position: relative !important; + margin-bottom: 8px !important; + display: flex !important; + justify-content: center !important; + align-items: center !important; + overflow: visible !important; + max-width: 100% !important; + height: 280px !important; /* Fixed height keeps the rows aligned */ + min-height: 280px !important; +} + +/* Centre the Gradio Plot component - layered selectors to make sure they match */ +.chart-with-toggle > div, +.chart-with-toggle > div > div, +.chart-with-toggle .plot-container, +.chart-with-toggle [class*="plot"] { + display: flex !important; + justify-content: center !important; + align-items: center !important; + margin: 0 auto !important; + width: 100% !important; +} + +/* Centre the Plotly chart - scale the 3D view to fit */ +.plot-container .js-plotly-plot, +.plot-container .plotly, +.plot-container > div { + margin: 0 auto !important; + max-width: 100% !important; +} + +/* Scale the 3D chart to the container - keep the aspect ratio */ +.plot-container svg, +.plot-container .main-svg { + max-width: 100% !important; + height: auto !important; +} + +/* Floating toggle container - absolute positioned at top-right */ +.view-toggle-float { + position: absolute !important; + top: 4px !important; + right: auto !important; + left: 50px !important; + z-index: 100 !important; + height: 28px !important; /* Fixed height */ + margin: 0 !important; + padding: 0 !important; + display: flex !important; + gap: 0 !important; + background: rgba(26, 10, 46, 0.85) !important; + border: 1px solid rgba(124, 58, 237, 0.3) !important; + border-radius: 4px !important; + padding: 2px !important; + width: auto !important; + min-width: auto !important; + max-width: fit-content !important; + flex-direction: row !important; + align-items: center !important; + justify-content: flex-end !important; +} + +/* Compact toggle buttons - side by side */ +/* Force row to not expand */ +.view-toggle-float > div, +.view-toggle-float .flex, +.view-toggle-float [class*="flex"] { + width: auto !important; + min-width: auto !important; + flex: 0 0 auto !important; + display: flex !important; + flex-direction: row !important; +} + +/* Gradio Button override - target internal button element */ +.view-toggle-btn-compact, +.view-toggle-btn-compact > button, +.view-toggle-btn-compact button, +.view-toggle-btn-compact [data-testid="button"] { + width: 40px !important; + height: 24px !important; + min-width: 40px !important; + min-height: 24px !important; + max-width: 40px !important; + max-height: 24px !important; + flex: 0 0 40px !important; + padding: 0 !important; + margin: 0 !important; + font-size: 11px !important; + font-weight: 600 !important; + border: none !important; + cursor: pointer !important; + transition: all 0.2s ease !important; + background: transparent !important; + color: #94a3b8 !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + letter-spacing: -0.3px !important; + box-sizing: border-box !important; + flex-shrink: 0 !important; +} + +/* Left button - rounded left corners */ +.view-toggle-btn-compact.view-toggle-left, +.view-toggle-btn-compact.view-toggle-left > button { + border-radius: 2px 0 0 2px !important; + border-right: 1px solid rgba(124, 58, 237, 0.2) !important; +} + +/* Right button - rounded right corners */ +.view-toggle-btn-compact.view-toggle-right, +.view-toggle-btn-compact.view-toggle-right > button { + border-radius: 0 2px 2px 0 !important; +} + +/* Hover state - higher specificity */ +.view-toggle-btn-compact:hover, +.view-toggle-btn-compact:hover > button, +.view-toggle-btn-compact > button:hover { + color: #ffffff !important; + background: rgba(124, 58, 237, 0.2) !important; +} + +/* Non-active state - transparent background */ +.view-toggle-btn-compact:not(.view-active), +.view-toggle-btn-compact:not(.view-active) > button, +.view-toggle-btn-compact:not(.view-active) > button:active, +.view-toggle-float .view-toggle-btn-compact:not(.view-active) { + background: transparent !important; + color: rgba(255, 255, 255, 0.6) !important; + border-color: rgba(124, 58, 237, 0.3) !important; +} + +/* Active state - golden - highest specificity */ +.view-toggle-btn-compact.view-active, +.view-toggle-btn-compact.view-active > button, +.view-toggle-btn-compact.view-active > button:active, +.view-toggle-float .view-toggle-btn-compact.view-active { + background: #FFC40E !important; + color: #1a0a2e !important; + border-color: #FFC40E !important; +} + +/* ===== Global 2D/3D switch in the control row ===== */ +/* .control-item forces min-width:0, which would collapse the switch to 0px */ +.control-item.all-view-item { + flex: 0 0 auto !important; + min-width: 200px !important; + width: 200px !important; +} +.all-view-toggle { + display: flex; + flex-direction: row; + align-items: center; + gap: 6px; +} +.all-view-btn { + flex: 0 1 auto !important; + min-width: 0 !important; + height: 30px !important; + padding: 0 10px !important; + font-size: 11px !important; + font-weight: 600 !important; + letter-spacing: 0.4px !important; + border-radius: 6px !important; + border: 1px solid rgba(124, 58, 237, 0.45) !important; + background: rgba(255, 255, 255, 0.04) !important; + color: rgba(255, 255, 255, 0.72) !important; + cursor: pointer !important; + white-space: nowrap !important; + transition: all 0.2s ease !important; +} +.all-view-btn:hover { + background: rgba(124, 58, 237, 0.28) !important; + border-color: rgba(124, 58, 237, 0.8) !important; + color: #ffffff !important; +} +.all-view-btn.view-active { + background: #FFC40E !important; + border-color: #FFC40E !important; + color: #1a0a2e !important; +} + +/* ===== Overlay panel: browser-side sweep (both layers stay visible) ===== */ +/* Popup shown when a class the current dataset does not have is clicked */ +#class-avail-toast { + position: fixed; + top: 26px; + left: 50%; + transform: translate(-50%, -12px); + z-index: 2147483000; + max-width: 70vw; + padding: 12px 20px; + border-radius: 10px; + background: linear-gradient(135deg, rgba(45, 27, 78, 0.97) 0%, rgba(26, 10, 46, 0.97) 100%); + border: 1px solid rgba(255, 196, 14, 0.55); + box-shadow: 0 8px 28px rgba(0, 0, 0, 0.55); + color: #ffffff; + font-size: 14px; + font-weight: 500; + text-align: center; + opacity: 0; + pointer-events: none; + transition: opacity 0.25s ease, transform 0.25s ease; +} +#class-avail-toast.show { + opacity: 1; + transform: translate(-50%, 0); +} + +/* Gradio removes visible=False components from the DOM, so keep helper triggers + off-screen instead - JavaScript can still click them. */ +.offscreen-trigger { + position: fixed !important; + left: -9999px !important; + top: 0 !important; + width: 1px !important; + height: 1px !important; + opacity: 0 !important; + pointer-events: none !important; +} + +/* Sub header for individual chart titles - fixed height for alignment */ +.col-header-sub { + font-size: 0.8rem !important; + color: #FFC40E !important; + font-weight: 500 !important; + padding: 4px 8px !important; + margin: 4px 0 !important; + background: transparent !important; + border: none !important; + text-align: center !important; + height: 24px !important; /* Fixed height */ + line-height: 16px !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; +} + +/* Plot containers */ +.plot-container { + position: relative !important; + border: none !important; + box-shadow: none !important; + background: transparent !important; +} + +/* 3D active state - golden glow */ +.chart-3d-active { + box-shadow: 0 0 0 1px rgba(255, 196, 14, 0.4), 0 0 15px rgba(255, 196, 14, 0.15) !important; + border-radius: 6px !important; +} + +/* Main content row - ensure three columns align */ +.equal-height > div, +[equal_height="true"] > div { + display: flex !important; + flex-direction: column !important; +} + +/* Ensure each column has consistent spacing */ +.equal-height .col-header-sub:first-of-type { + margin-top: 8px !important; +} + +/* Plot containers - no borders */ +.plot-container { + position: relative !important; + border: none !important; + box-shadow: none !important; + background: transparent !important; +} +""" + +# ==================== JavaScript for Loading Screen ==================== +LOADING_SCREEN_JS = """ + +""" + +# ==================== JavaScript for 2D/3D View Toggle ==================== +VIEW_TOGGLE_JS = """ + +""" + +# ==================== Global 2D/3D switch ==================== +ALL_VIEW_TOGGLE_HTML = ''' +
+ + +
+''' + +# ==================== Class availability per dataset ==================== +# Which class-filter buttons make sense for each dataset, taken from +# valid_classes in datasets//dataset_meta.json. Classes the dataset does +# not contain are greyed out, and clicking them answers with a popup instead of +# running the filter. The server-side guard in apply_class_filter stays as a +# second line of defence. +CLASS_AVAILABILITY_JS = """ + +""" + + +def build_class_availability_js(): + """Fill the availability script with each dataset's valid_classes.""" + availability = { + name: assets.load_dataset_meta(name).get("valid_classes", [0, 1]) + for name in assets.available_datasets() + } + return CLASS_AVAILABILITY_JS.replace("__CLASS_AVAILABILITY__", json.dumps(availability)) + + +# ==================== UI helpers: global 2D/3D switch ==================== +UI_HELPERS_JS = """ + +""" + +# ==================== JavaScript for Dropdown Position Fix ==================== +DROPDOWN_FIX_JS = """ + +""" + +# ==================== JavaScript for Class Filter ==================== +CLASS_FILTER_JS = """ + +""" + +# ==================== Build Interface ==================== +def create_interface(): + available_datasets = get_available_datasets() + if not available_datasets: + print("[warn] No dataset found under datasets/ -- the data source dropdown will be empty. " + "Download the models and datasets from Hugging Face first (see README Step 1).") + + # Only expose datasets that actually exist on disk + all_data_sources = available_datasets + + with gr.Blocks(title="EchMo-Vis") as demo: + # Inject the dropdown-positioning JavaScript + gr.HTML(DROPDOWN_FIX_JS) + # Inject the class-filter JavaScript + gr.HTML(CLASS_FILTER_JS) + + # Header with logo - logo top-right, title centred + logo_html = f'' if LOGO_BASE64 else "" + gr.HTML(f''' +
+
+
End-to-End Radar Echo Segmentation
+
Perception & Cognition Laboratory
+
+ {logo_html} +
+ ''') + + # Global style container + gr.HTML(''' + +
+ ''') + + with gr.Tabs(): + # Original Tab - Single Model + with gr.Tab("⚔️ EchMo vs. Traditional RSP", id="single"): + # Static legend - only used by the first tab + gr.HTML(''' +
+
BACKGROUND
+
Target
+
DFTJ
+
ISRJ
+
SIJ
+
WJ
+
NJ
+
CFAR-Target
+
+ ''', elem_classes="legend-static-host") + + # State used to track ground-truth visibility + has_gt_mask = gr.State(True) + + # Control bar - switches dynamically + with gr.Row(variant="panel", elem_classes="control-row"): + # Data Source + with gr.Column(scale=2, elem_classes="control-item"): + gr.HTML('Data Source') + data_source_dropdown = gr.Dropdown( + choices=all_data_sources, + value=all_data_sources[0] if all_data_sources else None, + show_label=False, + container=False, + elem_classes=["dark-dropdown"] + ) + + # Sequence + with gr.Column(scale=2, elem_classes="control-item"): + seq_label = gr.HTML('Sequence') + sequence_dropdown = gr.Dropdown( + choices=[], + value=None, + show_label=False, + container=False, + elem_classes=["dark-dropdown"], + visible=True + ) + + # Frame + with gr.Column(scale=2, elem_classes="control-item"): + frame_label = gr.HTML('Frame') + frame_dropdown = gr.Dropdown( + choices=[], + value=None, + show_label=False, + container=False, + elem_classes=["dark-dropdown"], + visible=True + ) + + # Global 2D/3D switch - applies to every chart that supports it + with gr.Column(scale=0, min_width=200, elem_classes="control-item all-view-item"): + gr.HTML('View (all charts)') + gr.HTML(ALL_VIEW_TOGGLE_HTML) + + # Run Button + with gr.Column(scale=0, min_width=120): + run_button = gr.Button("Run", variant="primary", elem_classes="run-btn") + + # Dynamic opacity state + overlay_alpha = gr.State(0.0) + # Result pinned by a click on the overlay panel: (layer, deadline). + # Only the click handler writes this, the timer just reads it, so a + # stale tick cannot undo the click. + overlay_manual = gr.State((-1, 0.0)) + echmo_mask_cache = gr.State(None) + cfar_mask_cache = gr.State(None) + n_classes_cache = gr.State(2) + + # Main content - the shared display area + with gr.Row(equal_height=True): + # First column: segmentation results (order after the swap: Raw -> GT -> Pred) + with gr.Column(scale=1, min_width=240): + gr.HTML('
Segmentation Results: Before & After
') + # Raw Echo with 2D/3D toggle inside chart + gr.HTML('
Raw Echo Input
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + raw_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + raw_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + raw_input_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + # After the swap: Ground Truth is in position 2 + gr.HTML('
Ground Truth
') + gt_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"], visible=True) + # Prediction Mask (EchMo + CFAR Overlay) + gr.HTML('
EchMo + CFAR Overlay
') + # elem_id is the hook the click-to-switch JavaScript uses + pred_mask_plot = gr.Plot(label="", show_label=False, container=True, + elem_classes=["plot-container"], elem_id="overlay-plot") + # Timer driving the dynamic-opacity animation + timer = gr.Timer(value=0.05, active=True) + # Kept in the DOM (off-screen) so JavaScript can click it + overlay_flip_trigger = gr.Button("flip", elem_id="overlay-flip-trigger", + elem_classes="offscreen-trigger") + + # Second column: EchMo + with gr.Column(scale=1, min_width=240): + gr.HTML('
EchMo Intermediate Features
') + # EchMo LMF with 2D/3D toggle inside chart + gr.HTML('
EchMo LMF
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + echmo_lmf_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + echmo_lmf_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + echmo_lmf_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + # EchMo MLDC with 2D/3D toggle inside chart + gr.HTML('
EchMo MLDC
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + echmo_mldc_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + echmo_mldc_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + echmo_mldc_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + # EchMo GDF with 2D/3D toggle inside chart + gr.HTML('
EchMo GDF
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + echmo_gdf_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + echmo_gdf_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + echmo_gdf_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + # Third column: traditional methods + with gr.Column(scale=1, min_width=240): + gr.HTML('
Traditional RSP Intermediate Results
') + # Trad LMF with 2D/3D toggle inside chart + gr.HTML('
Traditional LMF
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + trad_lmf_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + trad_lmf_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + trad_lmf_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + # Trad MTI with 2D/3D toggle inside chart + gr.HTML('
Traditional MTI
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + trad_mti_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + trad_mti_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + trad_mti_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + # Trad MTD with 2D/3D toggle inside chart + gr.HTML('
Traditional MTD
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + trad_mtd_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + trad_mtd_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + trad_mtd_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + # Status + status_text = gr.Textbox( + label="", + value="", + interactive=False, + elem_classes="status-bar", + show_label=False, + container=False, + lines=1 + ) + + # ==================== Event Handlers ==================== + + def on_data_source_change(data_source): + """Refresh the Sequence dropdown when the Data Source changes""" + sequences = get_sequences(data_source) + return ( + gr.update(choices=sequences, value=sequences[0] if sequences else None, visible=True), + gr.update(value='Sequence'), + gr.update(value='Frame') + ) + + def on_sequence_change(data_source, seq_name): + """When Sequence changes, update Frame list""" + if not seq_name: + return gr.update(choices=[], value=None) + frames = get_frames(data_source, seq_name) + return gr.update(choices=frames, value=frames[0] if frames else None) + + def run_processing(data_source, sequence, frame): + """Unified run processing function with 2D/3D view support""" + try: + results = run_inference(data_source, sequence, frame) + + has_gt = results[11] if len(results) > 11 else False + n_classes = _global_results.get('seg_n_classes', 2) + + # After swap: results[1] is ground_truth, results[2] is pred_mask, results[9] is cfar_mask + gt_fig = arr2plot(results[1], is_mask=True, title=None, n_classes=n_classes) if results[1] is not None else go.Figure() + + # Cache the EchMo and CFAR masks for the animation + echmo_mask = results[2] if len(results) > 2 else None + cfar_mask = results[9] if len(results) > 9 else None + + # Build the initial overlay figure (opacity 0) + if echmo_mask is not None and cfar_mask is not None: + overlay_fig = create_overlay_figure(echmo_mask, cfar_mask, alpha=0.0, n_classes=n_classes) + else: + overlay_fig = go.Figure() + + # Use get_plot_for_chart so the 2D/3D view toggle works + outputs = [ + get_plot_for_chart('raw', results[0], title=None), # 0: raw_input_plot + gt_fig, # 1: gt_plot + overlay_fig, # 2: pred_mask_plot (overlay) + get_plot_for_chart('echmo_lmf', results[3], title=None), # 3: echmo_lmf_plot + get_plot_for_chart('trad_lmf', results[4], title=None), # 4: trad_lmf_plot + get_plot_for_chart('echmo_mldc', results[5], title=None), # 5: echmo_mldc_plot + get_plot_for_chart('trad_mti', results[6], title=None), # 6: trad_mti_plot + get_plot_for_chart('echmo_gdf', results[7], title=None), # 7: echmo_gdf_plot + get_plot_for_chart('trad_mtd', results[8], title=None), # 8: trad_mtd_plot + results[10] if len(results) > 10 else "Error: No status", # 9: status_text + has_gt, # 10: has_gt_mask + 0.0, # 11: overlay_alpha + echmo_mask, # 12: echmo_mask_cache + cfar_mask, # 13: cfar_mask_cache + n_classes # 14: n_classes_cache + ] + + return outputs + except Exception as e: + # On error return empty figures plus a message + error_msg = f"Error in run_processing: {str(e)}" + print(error_msg) + import traceback + traceback.print_exc() + empty_fig = go.Figure() + return [ + empty_fig, empty_fig, empty_fig, empty_fig, empty_fig, + empty_fig, empty_fig, empty_fig, empty_fig, + error_msg, False, 0.0, None, None, 2 + ] + + def update_gt_visibility(has_gt): + """Update GT plot visibility based on whether GT exists""" + return gr.update(visible=has_gt) + + # ==================== 2D/3D View Toggle Handlers ==================== + + def toggle_raw_view_2d(): + """Toggle Raw Echo to 2D view""" + try: + data = _view_cache.get_data('raw') + _view_cache.set_view_mode('raw', '2d') + plot = get_plot_for_chart('raw', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + except Exception as e: + print(f"Error in toggle_raw_view_2d: {e}") + return go.Figure(), gr.update(), gr.update() + + def toggle_raw_view_3d(): + """Toggle Raw Echo to 3D view""" + try: + data = _view_cache.get_data('raw') + _view_cache.set_view_mode('raw', '3d') + plot = get_plot_for_chart('raw', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + except Exception as e: + print(f"Error in toggle_raw_view_3d: {e}") + return go.Figure(), gr.update(), gr.update() + + def toggle_echmo_lmf_view_2d(): + data = _view_cache.get_data('echmo_lmf') + _view_cache.set_view_mode('echmo_lmf', '2d') + plot = get_plot_for_chart('echmo_lmf', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + + def toggle_echmo_lmf_view_3d(): + data = _view_cache.get_data('echmo_lmf') + _view_cache.set_view_mode('echmo_lmf', '3d') + plot = get_plot_for_chart('echmo_lmf', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + + def toggle_echmo_mldc_view_2d(): + data = _view_cache.get_data('echmo_mldc') + _view_cache.set_view_mode('echmo_mldc', '2d') + plot = get_plot_for_chart('echmo_mldc', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + + def toggle_echmo_mldc_view_3d(): + data = _view_cache.get_data('echmo_mldc') + _view_cache.set_view_mode('echmo_mldc', '3d') + plot = get_plot_for_chart('echmo_mldc', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + + def toggle_echmo_gdf_view_2d(): + data = _view_cache.get_data('echmo_gdf') + _view_cache.set_view_mode('echmo_gdf', '2d') + plot = get_plot_for_chart('echmo_gdf', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + + def toggle_echmo_gdf_view_3d(): + data = _view_cache.get_data('echmo_gdf') + _view_cache.set_view_mode('echmo_gdf', '3d') + plot = get_plot_for_chart('echmo_gdf', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + + def toggle_trad_lmf_view_2d(): + data = _view_cache.get_data('trad_lmf') + _view_cache.set_view_mode('trad_lmf', '2d') + plot = get_plot_for_chart('trad_lmf', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + + def toggle_trad_lmf_view_3d(): + data = _view_cache.get_data('trad_lmf') + _view_cache.set_view_mode('trad_lmf', '3d') + plot = get_plot_for_chart('trad_lmf', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + + def toggle_trad_mti_view_2d(): + data = _view_cache.get_data('trad_mti') + _view_cache.set_view_mode('trad_mti', '2d') + plot = get_plot_for_chart('trad_mti', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + + def toggle_trad_mti_view_3d(): + data = _view_cache.get_data('trad_mti') + _view_cache.set_view_mode('trad_mti', '3d') + plot = get_plot_for_chart('trad_mti', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + + def toggle_trad_mtd_view_2d(): + data = _view_cache.get_data('trad_mtd') + _view_cache.set_view_mode('trad_mtd', '2d') + plot = get_plot_for_chart('trad_mtd', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + + def toggle_trad_mtd_view_3d(): + data = _view_cache.get_data('trad_mtd') + _view_cache.set_view_mode('trad_mtd', '3d') + plot = get_plot_for_chart('trad_mtd', data, title=None) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + + # ==================== Event Bindings ==================== + + data_source_dropdown.change( + fn=on_data_source_change, + inputs=data_source_dropdown, + outputs=[sequence_dropdown, seq_label, frame_label] + ) + + sequence_dropdown.change( + fn=on_sequence_change, + inputs=[data_source_dropdown, sequence_dropdown], + outputs=frame_dropdown + ) + + # Note: outputs order matches the interface component definition order + run_event = run_button.click( + fn=run_processing, + inputs=[data_source_dropdown, sequence_dropdown, frame_dropdown], + outputs=[ + raw_input_plot, gt_plot, pred_mask_plot, # Swapped order: Raw → GT → Pred (Overlay) + echmo_lmf_plot, trad_lmf_plot, echmo_mldc_plot, + trad_mti_plot, echmo_gdf_plot, trad_mtd_plot, + status_text, has_gt_mask, + overlay_alpha, echmo_mask_cache, cfar_mask_cache, n_classes_cache # cache state + ] + ) + + # Timer callback: advance the dynamic-opacity animation. The frame is + # built by overlay_frame(), which keeps a clicked result on screen + # until its pin expires. + timer.tick( + fn=overlay_frame, + inputs=[overlay_alpha, echmo_mask_cache, cfar_mask_cache, n_classes_cache, + overlay_manual], + outputs=[pred_mask_plot, overlay_alpha] + ) + + # Clicking the overlay panel jumps straight to the other result and + # pins it for OVERLAY_HOLD_SECONDS, so the next timer tick continues + # from the clicked result instead of snapping back to the old one. + def handle_overlay_click(alpha): + fig, phase, manual = overlay_flip(alpha) + if fig is None: + return gr.update(), phase, manual + return fig, phase, manual + + overlay_flip_trigger.click( + fn=handle_overlay_click, + inputs=[overlay_alpha], + outputs=[pred_mask_plot, overlay_alpha, overlay_manual] + ) + + has_gt_mask.change( + fn=update_gt_visibility, + inputs=has_gt_mask, + outputs=gt_plot + ) + + # 2D/3D View Toggle Event Bindings for Tab 1 + raw_view_2d.click(fn=toggle_raw_view_2d, inputs=[], outputs=[raw_input_plot, raw_view_2d, raw_view_3d]) + raw_view_3d.click(fn=toggle_raw_view_3d, inputs=[], outputs=[raw_input_plot, raw_view_2d, raw_view_3d]) + + echmo_lmf_view_2d.click(fn=toggle_echmo_lmf_view_2d, inputs=[], outputs=[echmo_lmf_plot, echmo_lmf_view_2d, echmo_lmf_view_3d]) + echmo_lmf_view_3d.click(fn=toggle_echmo_lmf_view_3d, inputs=[], outputs=[echmo_lmf_plot, echmo_lmf_view_2d, echmo_lmf_view_3d]) + + echmo_mldc_view_2d.click(fn=toggle_echmo_mldc_view_2d, inputs=[], outputs=[echmo_mldc_plot, echmo_mldc_view_2d, echmo_mldc_view_3d]) + echmo_mldc_view_3d.click(fn=toggle_echmo_mldc_view_3d, inputs=[], outputs=[echmo_mldc_plot, echmo_mldc_view_2d, echmo_mldc_view_3d]) + + echmo_gdf_view_2d.click(fn=toggle_echmo_gdf_view_2d, inputs=[], outputs=[echmo_gdf_plot, echmo_gdf_view_2d, echmo_gdf_view_3d]) + echmo_gdf_view_3d.click(fn=toggle_echmo_gdf_view_3d, inputs=[], outputs=[echmo_gdf_plot, echmo_gdf_view_2d, echmo_gdf_view_3d]) + + trad_lmf_view_2d.click(fn=toggle_trad_lmf_view_2d, inputs=[], outputs=[trad_lmf_plot, trad_lmf_view_2d, trad_lmf_view_3d]) + trad_lmf_view_3d.click(fn=toggle_trad_lmf_view_3d, inputs=[], outputs=[trad_lmf_plot, trad_lmf_view_2d, trad_lmf_view_3d]) + + trad_mti_view_2d.click(fn=toggle_trad_mti_view_2d, inputs=[], outputs=[trad_mti_plot, trad_mti_view_2d, trad_mti_view_3d]) + trad_mti_view_3d.click(fn=toggle_trad_mti_view_3d, inputs=[], outputs=[trad_mti_plot, trad_mti_view_2d, trad_mti_view_3d]) + + trad_mtd_view_2d.click(fn=toggle_trad_mtd_view_2d, inputs=[], outputs=[trad_mtd_plot, trad_mtd_view_2d, trad_mtd_view_3d]) + trad_mtd_view_3d.click(fn=toggle_trad_mtd_view_3d, inputs=[], outputs=[trad_mtd_plot, trad_mtd_view_2d, trad_mtd_view_3d]) + + def auto_load_on_start(): + empty_plots = [go.Figure()] * 9 + if not available_datasets: + return ([gr.update()] * 4 + [True] + empty_plots + + ["No dataset found under datasets/ - download the assets first (README Step 1).", + 0.0, None, None, 2]) + + dataset = available_datasets[0] + sequences = get_sequences(dataset) + if not sequences: + return ([gr.update(choices=sequences, value=None), + gr.update(visible=True, choices=[], value=None), + gr.update(value='Sequence'), + gr.update(value='Frame'), + True] + empty_plots + + [f"No sequence found in datasets/{dataset}", 0.0, None, None, 2]) + + seq = sequences[0] + frames = get_frames(dataset, seq) + if not frames: + return ([gr.update(choices=sequences, value=seq), + gr.update(visible=True, choices=[], value=None), + gr.update(value='Sequence'), + gr.update(value='Frame'), + True] + empty_plots + + [f"No frame found for {dataset}/{seq}", 0.0, None, None, 2]) + + frame = frames[0] + results = run_inference(dataset, seq, frame) + n_classes = _global_results.get('seg_n_classes', 2) + + # Cache the EChMo and CFAR masks + echmo_mask = results[2] if len(results) > 2 else None + cfar_mask = results[9] if len(results) > 9 else None + + # Build the initial overlay figure (opacity 0) + overlay_fig = go.Figure() + if echmo_mask is not None and cfar_mask is not None: + overlay_fig = create_overlay_figure(echmo_mask, cfar_mask, alpha=0.0, n_classes=n_classes) + + # Use get_plot_for_chart to support 2D/3D view toggle + plot_results = [ + get_plot_for_chart('raw', results[0], title=None), + arr2plot(results[1], is_mask=True, title=None, n_classes=n_classes) if results[1] is not None else go.Figure(), # Mask - 2D only + overlay_fig, # Overlay - 2D only + get_plot_for_chart('echmo_lmf', results[3], title=None), + get_plot_for_chart('trad_lmf', results[4], title=None), + get_plot_for_chart('echmo_mldc', results[5], title=None), + get_plot_for_chart('trad_mti', results[6], title=None), + get_plot_for_chart('echmo_gdf', results[7], title=None), + get_plot_for_chart('trad_mtd', results[8], title=None), + ] + + has_gt = results[11] if len(results) > 11 else (results[1] is not None) # Check results[1] after swap + + return [ + gr.update(choices=sequences, value=seq, visible=True), + gr.update(visible=True, choices=frames, value=frame), + gr.update(value='Sequence'), + gr.update(value='Frame'), + has_gt + ] + plot_results + [results[10], 0.0, echmo_mask, cfar_mask, n_classes] + + demo.load( + fn=auto_load_on_start, + inputs=None, + outputs=[ + sequence_dropdown, frame_dropdown, seq_label, frame_label, has_gt_mask, + raw_input_plot, gt_plot, pred_mask_plot, # Order after the swap (Overlay) + echmo_lmf_plot, trad_lmf_plot, echmo_mldc_plot, + trad_mti_plot, echmo_gdf_plot, trad_mtd_plot, + status_text, # status_text + overlay_alpha, echmo_mask_cache, cfar_mask_cache, n_classes_cache # cache state + ] + ) + + # New Tab - Model Comparison + with gr.Tab("🔥 Model Comparison", id="comparison"): + # Comparison tab states + cmp_has_gt_mask = gr.State(True) + # Currently selected class index (-1 = show all) + cmp_selected_class = gr.State(-1) + # Cache the last inference result so class filtering can redraw instantly + cmp_last_result = gr.State(None) + + # Hidden components for class filter JavaScript integration + with gr.Row(visible=False): + class_filter_input = gr.Textbox( + value="-1", + elem_id="class-filter-input", + interactive=True + ) + class_filter_trigger = gr.Button( + "Filter", + elem_id="class-filter-trigger", + visible=False + ) + + # Control Bar + with gr.Row(variant="panel", elem_classes="control-row"): + # Data Source + with gr.Column(scale=2, elem_classes="control-item"): + gr.HTML('Data Source') + cmp_data_source = gr.Dropdown( + choices=available_datasets, + value=available_datasets[0] if available_datasets else None, + show_label=False, + container=False, + elem_id="cmp-data-source", + elem_classes=["dark-dropdown"] + ) + + # Sequence + with gr.Column(scale=2, elem_classes="control-item"): + gr.HTML('Sequence') + cmp_sequence = gr.Dropdown( + choices=[], + value=None, + show_label=False, + container=False, + elem_classes=["dark-dropdown"] + ) + + # Frame + with gr.Column(scale=2, elem_classes="control-item"): + gr.HTML('Frame') + cmp_frame = gr.Dropdown( + choices=[], + value=None, + show_label=False, + container=False, + elem_classes=["dark-dropdown"] + ) + + # Global 2D/3D switch - applies to every chart that supports it + with gr.Column(scale=0, min_width=200, elem_classes="control-item all-view-item"): + gr.HTML('View (all charts)') + gr.HTML(ALL_VIEW_TOGGLE_HTML) + + # Run Button + with gr.Column(scale=0, min_width=120): + cmp_run_btn = gr.Button("Run", variant="primary", elem_classes="run-btn") + + # Interactive legend bar for class filtering (absolutely positioned top-right) + with gr.Row(): + with gr.Column(scale=0): + gr.HTML('''
''') + with gr.Column(scale=0, min_width=650, elem_classes="legend-btn-container"): + with gr.Row(variant="compact", elem_classes="legend-btn-inner"): + # BACKGROUND - clickable + cmp_bg_btn = gr.Button("BACKGROUND", interactive=True, + elem_classes=["legend-class-btn", "legend-c0"], min_width=115) + # Clickable class buttons (JavaScript adds the colour swatches) + cmp_target_btn = gr.Button("Target", interactive=True, + elem_classes=["legend-class-btn", "legend-c1"], min_width=75) + cmp_dftj_btn = gr.Button("DFTJ", interactive=True, + elem_classes=["legend-class-btn", "legend-c2"], min_width=65) + cmp_isrj_btn = gr.Button("ISRJ", interactive=True, + elem_classes=["legend-class-btn", "legend-c3"], min_width=65) + cmp_sij_btn = gr.Button("SIJ", interactive=True, + elem_classes=["legend-class-btn", "legend-c4"], min_width=60) + cmp_wj_btn = gr.Button("WJ", interactive=True, + elem_classes=["legend-class-btn", "legend-c5"], min_width=55) + cmp_nj_btn = gr.Button("NJ", interactive=True, + elem_classes=["legend-class-btn", "legend-c6"], min_width=55) + # Reset button + cmp_reset_btn = gr.Button("⟲", interactive=True, + elem_classes="legend-reset-btn", min_width=32) + + # Results Area - Row 1: Raw Echo, MTD and Ground Truth + with gr.Row(equal_height=True): + with gr.Column(scale=1, min_width=240): + gr.HTML('
Raw Echo Input
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + cmp_raw_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + cmp_raw_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + cmp_raw_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + with gr.Column(scale=1, min_width=240): + gr.HTML('
MTD Input
') + with gr.Column(elem_classes="chart-with-toggle"): + with gr.Row(elem_classes="view-toggle-float"): + cmp_mtd_view_2d = gr.Button("2D", elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]) + cmp_mtd_view_3d = gr.Button("3D", elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + cmp_mtd_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + with gr.Column(scale=1, min_width=240): + gr.HTML('
Ground Truth Mask
') + cmp_gt_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"], visible=True) + + # Results Area - Row 2: EchMo, TMVA-Net, DeepLabv3+ (all 2D only - masks) + with gr.Row(equal_height=True): + with gr.Column(scale=1, min_width=240): + gr.HTML('
EchMo
') + cmp_echmo_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + with gr.Column(scale=1, min_width=240): + gr.HTML('
TMVA-Net
') + cmp_tmva_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + with gr.Column(scale=1, min_width=240): + gr.HTML('
DeepLabv3+
') + cmp_deeplab_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + # Results Area - Row 3: U-Net, FCN-8s, ViT (all 2D only - masks) + with gr.Row(equal_height=True): + with gr.Column(scale=1, min_width=240): + gr.HTML('
U-Net
') + cmp_unet_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + with gr.Column(scale=1, min_width=240): + gr.HTML('
FCN-8s
') + cmp_fcn_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + with gr.Column(scale=1, min_width=240): + gr.HTML('
ViT
') + cmp_vit_plot = gr.Plot(label="", show_label=False, container=True, elem_classes=["plot-container"]) + + # Status + cmp_status = gr.Textbox( + label="", + value="", + interactive=False, + elem_classes="status-bar", + show_label=False, + container=False, + lines=1 + ) + + # ==================== Comparison Tab Event Handlers ==================== + + # 2D/3D View Toggle Handlers for Tab 2 + def toggle_cmp_raw_view_2d(): + """Toggle Comparison Raw Echo to 2D view""" + data = _view_cache.get_data('cmp_raw') + _view_cache.set_view_mode('cmp_raw', '2d') + plot = get_plot_for_chart('cmp_raw', data) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + + def toggle_cmp_raw_view_3d(): + """Toggle Comparison Raw Echo to 3D view""" + data = _view_cache.get_data('cmp_raw') + _view_cache.set_view_mode('cmp_raw', '3d') + plot = get_plot_for_chart('cmp_raw', data) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + + def toggle_cmp_mtd_view_2d(): + """Toggle Comparison MTD to 2D view""" + data = _view_cache.get_data('cmp_mtd') + _view_cache.set_view_mode('cmp_mtd', '2d') + plot = get_plot_for_chart('cmp_mtd', data) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left", "view-active"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right"]) + ) + + def toggle_cmp_mtd_view_3d(): + """Toggle Comparison MTD to 3D view""" + data = _view_cache.get_data('cmp_mtd') + _view_cache.set_view_mode('cmp_mtd', '3d') + plot = get_plot_for_chart('cmp_mtd', data) + return ( + plot, + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-left"]), + gr.update(elem_classes=["view-toggle-btn-compact", "view-toggle-right", "view-active"]) + ) + + def on_cmp_data_source_change(dataset_name): + """When comparison data source changes""" + if not dataset_name: + return gr.update(choices=[], value=None) + sequences = get_sequences(dataset_name) + return gr.update(choices=sequences, value=sequences[0] if sequences else None) + + def on_cmp_sequence_change(dataset_name, seq_name): + """When comparison sequence changes""" + if not dataset_name or not seq_name: + return gr.update(choices=[], value=None) + # Check that seq_name belongs to the current dataset + valid_sequences = get_sequences(dataset_name) + if seq_name not in valid_sequences: + # If seq_name is invalid, fall back to the first valid sequence + if valid_sequences: + seq_name = valid_sequences[0] + else: + return gr.update(choices=[], value=None) + frames = get_frames(dataset_name, seq_name) + return gr.update(choices=frames, value=frames[0] if frames else None) + + def run_comparison_processing(dataset_name, seq_name, frame_name): + """Run comparison inference with caching and 2D/3D view support""" + result, msg = run_comparison_inference(dataset_name, seq_name, frame_name) + + if result is None: + return [go.Figure()] * 9 + [msg, False, None, -1] + + n_classes = result.get('n_classes', 2) + has_gt = result['gt_mask'] is not None + + # Store the dataset name in the result for later class checks + result['dataset_name'] = dataset_name + + # Build the status message + display_msg = f"✓ Compared 6 models on {dataset_name}/{seq_name}/{frame_name}" + + # Cache raw data for 2D/3D view toggle + _view_cache.cache_data('cmp_raw', result['raw_echo']) + _view_cache.cache_data('cmp_mtd', result['mtd']) + + plots = [ + get_plot_for_chart('cmp_raw', result['raw_echo']), # Support 2D/3D + get_plot_for_chart('cmp_mtd', result['mtd']), # Support 2D/3D + arr2plot(result['gt_mask'], is_mask=True, n_classes=n_classes) if result['gt_mask'] is not None else go.Figure(), # Mask - 2D only + arr2plot(result['predictions'].get('echmo'), is_mask=True, n_classes=n_classes) if result['predictions'].get('echmo') is not None else go.Figure(), + arr2plot(result['predictions'].get('tmva_net_sv'), is_mask=True, n_classes=n_classes) if result['predictions'].get('tmva_net_sv') is not None else go.Figure(), + arr2plot(result['predictions'].get('deeplabv3plus'), is_mask=True, n_classes=n_classes) if result['predictions'].get('deeplabv3plus') is not None else go.Figure(), + arr2plot(result['predictions'].get('unet'), is_mask=True, n_classes=n_classes) if result['predictions'].get('unet') is not None else go.Figure(), + arr2plot(result['predictions'].get('fcn8s'), is_mask=True, n_classes=n_classes) if result['predictions'].get('fcn8s') is not None else go.Figure(), + arr2plot(result['predictions'].get('vit'), is_mask=True, n_classes=n_classes) if result['predictions'].get('vit') is not None else go.Figure(), + display_msg, + has_gt, + result, # cached result + -1 # Reset the selected class back to "all" + ] + return plots + + def apply_class_filter(filter_input, cached_result): + """Apply class filter to cached results - only updates last 6 model plots""" + # Parse the input + try: + parts = filter_input.split(',') + target_class_idx = int(parts[0]) if parts else -1 + except: + target_class_idx = -1 + + # Class name mapping + class_names = { + 0: 'BACKGROUND', + 1: 'Target', + 2: 'DFTJ', + 3: 'ISRJ', + 4: 'SIJ', + 5: 'WJ', + 6: 'NJ', + 7: 'CFAR-Target' + } + + # Valid classes come from valid_classes in each dataset_meta.json + # NOTE: this is the UI class-filter whitelist, not the model output channel count nb_classes + dataset_valid_classes = { + name: assets.load_dataset_meta(name).get("valid_classes", [0, 1]) + for name in assets.available_datasets() + } + + # No cached result yet - return an error + if cached_result is None: + return [go.Figure()] * 6 + ["⚠ No data. Please run inference first.", -1] + + # Get the dataset name + dataset_name = cached_result.get('dataset_name') or next(iter(assets.available_datasets()), None) + n_classes = cached_result.get('n_classes', 2) + + # If the target is "all" (-1), show the full segmentation + if target_class_idx == -1: + # Return the full segmentation figure + return [ + arr2plot(cached_result['predictions'].get('echmo'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('echmo') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('tmva_net_sv'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('tmva_net_sv') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('deeplabv3plus'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('deeplabv3plus') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('unet'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('unet') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('fcn8s'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('fcn8s') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('vit'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('vit') is not None else go.Figure(), + "✓ Restored full segmentation view", + -1 + ] + + # Validate the class against the dataset + valid_classes = dataset_valid_classes.get(dataset_name, [0, 1]) + if target_class_idx not in valid_classes: + class_name = class_names.get(target_class_idx, f"Class {target_class_idx}") + # This dataset does not have that class - return the current figure unchanged + return [ + arr2plot(cached_result['predictions'].get('echmo'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('echmo') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('tmva_net_sv'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('tmva_net_sv') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('deeplabv3plus'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('deeplabv3plus') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('unet'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('unet') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('fcn8s'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('fcn8s') is not None else go.Figure(), + arr2plot(cached_result['predictions'].get('vit'), is_mask=True, n_classes=n_classes) if cached_result['predictions'].get('vit') is not None else go.Figure(), + f"⚠ {dataset_name} does not have category '{class_name}'. View unchanged.", + -1 + ] + + # Class colour map (matches the legend buttons) + class_colors = { + 0: '#440154', # BACKGROUND - dark purple + 1: '#FDE725', # Target - yellow + 2: '#B71C1C', # DFTJ - deep red + 3: '#E53935', # ISRJ - red + 4: '#EF9A9A', # SIJ - light red + 5: '#2563EB', # WJ - blue + 6: '#7DD3FC' # BJ - light blue + } + + # Page theme background colour (for the 0 values of the binary mask) + theme_bg_color = '#1a0a2e' + + # Build the binary mask (using the class colour) + def create_binary_plot_colored(pred_mask, target_idx, class_name): + if pred_mask is None: + return go.Figure() + + # Pick the colour of the target class + target_color = class_colors.get(target_idx, '#FDE725') + + # Build the binary mask - uint8 avoids floating-point precision issues + binary_mask = (pred_mask == target_idx).astype(np.uint8) + + # Build a heatmap with custom colours + # 0 uses a transparent/dark background, 1 uses the class colour + colorscale = [ + [0, 'rgba(24, 24, 38, 1)'], # Theme background colour #181826 + [1, target_color] + ] + + # Array dimensions (doppler, range) + doppler_cells, range_cells = binary_mask.shape + + # Compute ticks - consistent with arr2plot + range_step = max(1, range_cells // 8) + doppler_step = max(1, doppler_cells // 6) + range_ticks = list(range(0, range_cells, range_step)) + doppler_ticks = list(range(0, doppler_cells, doppler_step)) + + fig = go.Figure(data=go.Heatmap( + z=binary_mask, + colorscale=colorscale, + showscale=False, + zmin=0, + zmax=1, + hovertemplate='%{y:.0f}, %{x:.0f}' + )) + + # Layout identical to arr2plot + fig.update_layout( + margin=dict(l=0, r=0, t=0, b=10), + xaxis_showgrid=False, + yaxis_showgrid=False, + xaxis=dict( + title=dict(text='Range cell', font=dict(size=11, color='#ffffff')), + showticklabels=True, + tickmode='array', + tickvals=range_ticks, + ticktext=[str(i) for i in range_ticks], + tickfont=dict(size=9, color='#ffffff'), + side='bottom' + ), + yaxis=dict( + title=dict(text='Doppler cell', font=dict(size=11, color='#ffffff')), + showticklabels=True, + tickmode='array', + tickvals=doppler_ticks, + ticktext=[str(i) for i in doppler_ticks], + tickfont=dict(size=9, color='#ffffff'), + autorange='reversed' + ), + height=280, + paper_bgcolor='rgba(0,0,0,0)', + plot_bgcolor='rgba(0,0,0,0)' + ) + + return fig + + class_name = class_names.get(target_class_idx, f"Class {target_class_idx}") + + # Return binary-mask figures (only the six model plots are updated) + return [ + create_binary_plot_colored(cached_result['predictions'].get('echmo'), target_class_idx, class_name), + create_binary_plot_colored(cached_result['predictions'].get('tmva_net_sv'), target_class_idx, class_name), + create_binary_plot_colored(cached_result['predictions'].get('deeplabv3plus'), target_class_idx, class_name), + create_binary_plot_colored(cached_result['predictions'].get('unet'), target_class_idx, class_name), + create_binary_plot_colored(cached_result['predictions'].get('fcn8s'), target_class_idx, class_name), + create_binary_plot_colored(cached_result['predictions'].get('vit'), target_class_idx, class_name), + f"✓ Isolating class: {class_name} | Binary mask view", + target_class_idx + ] + + def update_cmp_gt_visibility(has_gt): + """Update GT plot visibility""" + return gr.update(visible=has_gt) + + # ==================== Comparison Tab Event Bindings ==================== + + cmp_data_source.change( + fn=on_cmp_data_source_change, + inputs=cmp_data_source, + outputs=cmp_sequence + ) + + cmp_sequence.change( + fn=on_cmp_sequence_change, + inputs=[cmp_data_source, cmp_sequence], + outputs=cmp_frame + ) + + cmp_run_btn.click( + fn=run_comparison_processing, + inputs=[cmp_data_source, cmp_sequence, cmp_frame], + outputs=[ + cmp_raw_plot, cmp_mtd_plot, cmp_gt_plot, cmp_echmo_plot, cmp_tmva_plot, + cmp_deeplab_plot, cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_has_gt_mask, cmp_last_result, cmp_selected_class + ] + ) + + # 2D/3D View Toggle Event Bindings for Tab 2 + cmp_raw_view_2d.click(fn=toggle_cmp_raw_view_2d, inputs=[], outputs=[cmp_raw_plot, cmp_raw_view_2d, cmp_raw_view_3d]) + cmp_raw_view_3d.click(fn=toggle_cmp_raw_view_3d, inputs=[], outputs=[cmp_raw_plot, cmp_raw_view_2d, cmp_raw_view_3d]) + + cmp_mtd_view_2d.click(fn=toggle_cmp_mtd_view_2d, inputs=[], outputs=[cmp_mtd_plot, cmp_mtd_view_2d, cmp_mtd_view_3d]) + cmp_mtd_view_3d.click(fn=toggle_cmp_mtd_view_3d, inputs=[], outputs=[cmp_mtd_plot, cmp_mtd_view_2d, cmp_mtd_view_3d]) + + # Class-filter button events - plain Gradio Buttons + def on_class_btn_click(btn_idx, current_selected, cached_result): + """Handle a class-button click""" + # Clicking the selected button again clears the selection (show all) + if current_selected == btn_idx: + return apply_class_filter("-1", cached_result) + return apply_class_filter(str(btn_idx), cached_result) + + # Bind the individual class buttons + cmp_bg_btn.click( + fn=lambda sel, cache: on_class_btn_click(0, sel, cache), + inputs=[cmp_selected_class, cmp_last_result], + outputs=[cmp_echmo_plot, cmp_tmva_plot, cmp_deeplab_plot, + cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_selected_class] + ) + cmp_target_btn.click( + fn=lambda sel, cache: on_class_btn_click(1, sel, cache), + inputs=[cmp_selected_class, cmp_last_result], + outputs=[cmp_echmo_plot, cmp_tmva_plot, cmp_deeplab_plot, + cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_selected_class] + ) + cmp_dftj_btn.click( + fn=lambda sel, cache: on_class_btn_click(2, sel, cache), + inputs=[cmp_selected_class, cmp_last_result], + outputs=[cmp_echmo_plot, cmp_tmva_plot, cmp_deeplab_plot, + cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_selected_class] + ) + cmp_isrj_btn.click( + fn=lambda sel, cache: on_class_btn_click(3, sel, cache), + inputs=[cmp_selected_class, cmp_last_result], + outputs=[cmp_echmo_plot, cmp_tmva_plot, cmp_deeplab_plot, + cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_selected_class] + ) + cmp_sij_btn.click( + fn=lambda sel, cache: on_class_btn_click(4, sel, cache), + inputs=[cmp_selected_class, cmp_last_result], + outputs=[cmp_echmo_plot, cmp_tmva_plot, cmp_deeplab_plot, + cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_selected_class] + ) + cmp_wj_btn.click( + fn=lambda sel, cache: on_class_btn_click(5, sel, cache), + inputs=[cmp_selected_class, cmp_last_result], + outputs=[cmp_echmo_plot, cmp_tmva_plot, cmp_deeplab_plot, + cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_selected_class] + ) + cmp_nj_btn.click( + fn=lambda sel, cache: on_class_btn_click(6, sel, cache), + inputs=[cmp_selected_class, cmp_last_result], + outputs=[cmp_echmo_plot, cmp_tmva_plot, cmp_deeplab_plot, + cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_selected_class] + ) + + # Reset button + cmp_reset_btn.click( + fn=lambda cache: apply_class_filter("-1", cache), + inputs=[cmp_last_result], + outputs=[cmp_echmo_plot, cmp_tmva_plot, cmp_deeplab_plot, + cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_selected_class] + ) + + cmp_has_gt_mask.change( + fn=update_cmp_gt_visibility, + inputs=cmp_has_gt_mask, + outputs=cmp_gt_plot + ) + + # Auto-load on start for comparison tab + def cmp_auto_load(): + if not available_datasets: + return [gr.update(choices=[], value=None)] * 2 + [go.Figure()] * 9 + ["No datasets", False, None, -1] + + dataset = available_datasets[0] + sequences = get_sequences(dataset) + if not sequences: + return [gr.update(choices=[], value=None), gr.update(choices=[], value=None)] + [go.Figure()] * 9 + ["No sequences", False, None, -1] + + seq = sequences[0] + frames = get_frames(dataset, seq) + if not frames: + return [gr.update(choices=sequences, value=seq), gr.update(choices=[], value=None)] + [go.Figure()] * 9 + ["No frames", False, None, -1] + + frame = frames[0] + result, msg = run_comparison_inference(dataset, seq, frame) + + if result is None: + return [gr.update(choices=sequences, value=seq), gr.update(choices=frames, value=frame)] + [go.Figure()] * 9 + [msg, False, None, -1] + + n_classes = result.get('n_classes', 2) + has_gt = result['gt_mask'] is not None + display_msg = f"✓ Compared 6 models on {dataset}/{seq}/{frame}" + + # Cache raw data for 2D/3D view toggle + _view_cache.cache_data('cmp_raw', result['raw_echo']) + _view_cache.cache_data('cmp_mtd', result['mtd']) + + plots = [ + gr.update(choices=sequences, value=seq), + gr.update(choices=frames, value=frame), + get_plot_for_chart('cmp_raw', result['raw_echo']), # Support 2D/3D + get_plot_for_chart('cmp_mtd', result['mtd']), # Support 2D/3D + arr2plot(result['gt_mask'], is_mask=True, n_classes=n_classes) if result['gt_mask'] is not None else go.Figure(), # Mask - 2D only + arr2plot(result['predictions'].get('echmo'), is_mask=True, n_classes=n_classes) if result['predictions'].get('echmo') is not None else go.Figure(), + arr2plot(result['predictions'].get('tmva_net_sv'), is_mask=True, n_classes=n_classes) if result['predictions'].get('tmva_net_sv') is not None else go.Figure(), + arr2plot(result['predictions'].get('deeplabv3plus'), is_mask=True, n_classes=n_classes) if result['predictions'].get('deeplabv3plus') is not None else go.Figure(), + arr2plot(result['predictions'].get('unet'), is_mask=True, n_classes=n_classes) if result['predictions'].get('unet') is not None else go.Figure(), + arr2plot(result['predictions'].get('fcn8s'), is_mask=True, n_classes=n_classes) if result['predictions'].get('fcn8s') is not None else go.Figure(), + arr2plot(result['predictions'].get('vit'), is_mask=True, n_classes=n_classes) if result['predictions'].get('vit') is not None else go.Figure(), + display_msg, + has_gt, + result, # cached result + -1 # Nothing selected by default + ] + return plots + + demo.load( + fn=cmp_auto_load, + inputs=None, + outputs=[ + cmp_sequence, cmp_frame, + cmp_raw_plot, cmp_mtd_plot, cmp_gt_plot, cmp_echmo_plot, cmp_tmva_plot, + cmp_deeplab_plot, cmp_unet_plot, cmp_fcn_plot, cmp_vit_plot, + cmp_status, cmp_has_gt_mask, cmp_last_result, cmp_selected_class + ] + ) + + # Close the tabs-wrapper div + gr.HTML('
') + + return demo + + +# ==================== Main Entry ==================== +if __name__ == "__main__": + import sys + + # Port: honour the PORT env var; Hugging Face Spaces expect 7860 by default + port = int(os.environ.get("PORT", 7860)) + + print("=" * 60, file=sys.stderr) + print(" End-to-End Radar Echo Segmentation", file=sys.stderr) + print("=" * 60, file=sys.stderr) + print(f" Server: http://0.0.0.0:{port}", file=sys.stderr) + print("=" * 60, file=sys.stderr) + + demo = create_interface() + demo.launch( + server_name="0.0.0.0", + server_port=port, + share=False, + show_error=True, + theme=gr.themes.Base(), + css=CUSTOM_CSS, + head=LOADING_SCREEN_JS + VIEW_TOGGLE_JS + UI_HELPERS_JS + build_class_availability_js(), + max_file_size="50mb" + ) diff --git a/asset_paths.py b/asset_paths.py new file mode 100644 index 0000000000000000000000000000000000000000..7fdcb04d80a6dfa1ca45564e628fd3d5df254b07 --- /dev/null +++ b/asset_paths.py @@ -0,0 +1,225 @@ +""" +Central asset path resolution for the EchMo radar echo segmentation app. + +Why this module exists +---------------------- +Model weights and datasets are not stored in the code repository; they are +pulled from Hugging Face. Those paths used to be hard-coded in `app.py` +(a `MODEL_PATHS` dict plus several `if dataset_name == ...` branches), so any +retrain that renamed a run directory -- or any new dataset -- required editing +the application code. + +Now everything dataset-specific is *discovered from disk*: + + models///config.json -> run folder + "model" field + models///results/.pt -> weights (filename == model) + datasets//dataset_meta.json -> per-dataset behaviour + +`datasets//dataset_meta.json` fields (all optional) +----------------------------------------------------------- + display_name str label shown in the UI (default: folder name) + full_name str paper abbreviation / expansion (informational) + scenario str short description (informational) + order int sort order of the dataset dropdown + mtd_fftshift bool apply fftshift after the Doppler FFT in MTD + mtd_amp_dir str sequence sub-folder holding the MTD amplitude .npy + valid_classes list classes offered by the class filter in the UI + run_overrides dict {"model": "run_folder"} to pin a specific run when a + dataset contains several runs of the same model + +IMPORTANT: `valid_classes` is *not* `nb_classes`. `nb_classes` comes from the +model `config.json` and is the number of output channels used for the +segmentation colour scale. HiL-RED, for instance, trains with 9 channels while +only classes 0-6 actually occur in the annotations. + +This module uses the standard library only, so it can be imported by scripts +without pulling in torch/gradio. +""" + +from __future__ import annotations + +import json +import os + +# Pseudo dataset used by the "upload your own data" mode. It is not a real +# folder under datasets/ and must never be treated as one. +CUSTOM_DATASET = "Custom Data" + +DATASETS_ROOT = "datasets" +MODELS_ROOT = "models" + +INDEX_FILENAME = "light_dataset_frame_oriented.json" +META_FILENAME = "dataset_meta.json" +COEFS_DIRNAME = "coefs" +TRANSMIT_FILENAME = "s_tx.mat" + +DEFAULT_META = { + "mtd_fftshift": True, + "mtd_amp_dir": "range_doppler_MTD", + "valid_classes": [0, 1], + "run_overrides": {}, +} + +_meta_cache: dict[str, dict] = {} + + +# -------------------------------------------------------------------------- +# helpers +# -------------------------------------------------------------------------- +def read_json(path: str, default=None): + # utf-8-sig reads plain UTF-8 unchanged and additionally strips a leading BOM. + # Without it a BOM (editors and Excel-like tools add one happily) makes + # json.load raise, the file is silently ignored and every setting falls back to + # DEFAULT_META - that is how HiL-RED once ended up with valid_classes [0, 1]. + try: + with open(path, "r", encoding="utf-8-sig") as handle: + return json.load(handle) + except (OSError, ValueError): + return default + + +# -------------------------------------------------------------------------- +# datasets +# -------------------------------------------------------------------------- +def dataset_dir(dataset: str) -> str: + return os.path.join(DATASETS_ROOT, dataset) + + +def index_path(dataset: str) -> str: + return os.path.join(dataset_dir(dataset), INDEX_FILENAME) + + +def meta_path(dataset: str) -> str: + return os.path.join(dataset_dir(dataset), META_FILENAME) + + +def coefs_dir(dataset: str) -> str: + return os.path.join(dataset_dir(dataset), COEFS_DIRNAME) + + +def transmit_signal_path(dataset: str) -> str: + return os.path.join(coefs_dir(dataset), TRANSMIT_FILENAME) + + +def load_dataset_meta(dataset: str) -> dict: + """Merged dataset_meta.json (cached). Unknown datasets fall back to defaults.""" + if dataset not in _meta_cache: + meta = dict(DEFAULT_META) + loaded = read_json(meta_path(dataset), {}) + if isinstance(loaded, dict): + meta.update(loaded) + meta.setdefault("display_name", dataset) + _meta_cache[dataset] = meta + return _meta_cache[dataset] + + +def clear_meta_cache() -> None: + _meta_cache.clear() + + +def available_datasets() -> list[str]: + """Dataset folders that actually have a frame index, in display order.""" + if not os.path.isdir(DATASETS_ROOT): + return [] + found = [] + for name in os.listdir(DATASETS_ROOT): + if name == CUSTOM_DATASET or not os.path.isdir(dataset_dir(name)): + continue + if not os.path.isfile(index_path(name)): + continue # without the index the dataset cannot be shown at all + found.append((load_dataset_meta(name).get("order", 10_000), name)) + found.sort(key=lambda item: (item[0], item[1])) + return [name for _, name in found] + + +def load_dataset_index(dataset: str) -> dict: + """{sequence: [frames]} -- {} when missing or not valid strict JSON.""" + data = read_json(index_path(dataset), None) + return data if isinstance(data, dict) else {} + + +def get_sequences(dataset: str) -> list[str]: + if dataset == CUSTOM_DATASET: + return [] + return list(load_dataset_index(dataset).keys()) + + +def get_frames(dataset: str, sequence: str) -> list: + if dataset == CUSTOM_DATASET or not sequence: + return [] + return load_dataset_index(dataset).get(sequence, []) + + +def echo_path(dataset: str, sequence: str, frame: str) -> str: + return os.path.join(dataset_dir(dataset), sequence, "range_doppler_echo", f"{frame}.npy") + + +def annotation_path(dataset: str, sequence: str, frame: str) -> str: + return os.path.join(dataset_dir(dataset), sequence, "annotations", "dense", frame, "range_doppler.npy") + + +def mtd_amp_path(dataset: str, sequence: str, frame: str) -> str: + return os.path.join(dataset_dir(dataset), sequence, load_dataset_meta(dataset)["mtd_amp_dir"], f"{frame}.npy") + + +# -------------------------------------------------------------------------- +# models +# -------------------------------------------------------------------------- +def runs_dir(dataset: str) -> str: + return os.path.join(MODELS_ROOT, dataset) + + +def run_dir(dataset: str, run_folder: str) -> str: + return os.path.join(runs_dir(dataset), run_folder) + + +def run_config_path(dataset: str, run_folder: str) -> str: + return os.path.join(run_dir(dataset, run_folder), "config.json") + + +def run_weights_path(dataset: str, run_folder: str, filename: str) -> str: + return os.path.join(run_dir(dataset, run_folder), "results", filename) + + +def load_run_config(dataset: str, run_folder: str) -> dict: + data = read_json(run_config_path(dataset, run_folder), None) + return data if isinstance(data, dict) else {} + + +def discover_runs(dataset: str) -> dict[str, tuple[str, str]]: + """ + {model_name: (run_folder, weights_filename)} discovered from disk. + + A run folder qualifies when its config.json declares `"model"` and + `results/.pt` exists. When several runs train the same model the + alphabetically first folder wins, unless `run_overrides` in + dataset_meta.json pins a specific one. + """ + runs: dict[str, tuple[str, str]] = {} + if not os.path.isdir(runs_dir(dataset)): + return runs + + for folder in sorted(os.listdir(runs_dir(dataset))): + if not os.path.isdir(run_dir(dataset, folder)): + continue + cfg = load_run_config(dataset, folder) + model = cfg.get("model") or cfg.get("model_name") + if not model: + continue + filename = f"{model}.pt" + if not os.path.isfile(run_weights_path(dataset, folder, filename)): + continue + runs.setdefault(model, (folder, filename)) + + for model, folder in (load_dataset_meta(dataset).get("run_overrides") or {}).items(): + filename = f"{model}.pt" + if os.path.isfile(run_weights_path(dataset, folder, filename)): + runs[model] = (folder, filename) + else: + print(f"[warn] run_overrides: '{folder}' for model '{model}' in '{dataset}' is not usable") + + return runs + + +def model_names(dataset: str) -> list[str]: + return sorted(discover_runs(dataset)) diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-10dB/annotations/dense/2025090809332621314/range_doppler.npy b/datasets/HiL-RED/barrage_narrow_jamming_-10dB/annotations/dense/2025090809332621314/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..54ff259cdd93291d713042f725663bf34b7c8f53 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-10dB/annotations/dense/2025090809332621314/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70ecf065fbac4a338dcaf36d00be9338d92758246197391490a10b2a98cece19 +size 131200 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-10dB/range_doppler_MTD/2025090809332621314.npy b/datasets/HiL-RED/barrage_narrow_jamming_-10dB/range_doppler_MTD/2025090809332621314.npy new file mode 100644 index 0000000000000000000000000000000000000000..51d0a8cbfe69fb7a164d705c280f5b5ee8cd9d46 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-10dB/range_doppler_MTD/2025090809332621314.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a46e58e8987890ad6f4e7bd699590cb27d6da378799a88d3704bdede55f341ea +size 2097280 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-10dB/range_doppler_echo/2025090809332621314.npy b/datasets/HiL-RED/barrage_narrow_jamming_-10dB/range_doppler_echo/2025090809332621314.npy new file mode 100644 index 0000000000000000000000000000000000000000..93f3777ea9f792e27974b5b0fc9bdcf255ed0168 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-10dB/range_doppler_echo/2025090809332621314.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e496283afdbfb8fde85796edaedc5c07be412aa04281fab099b629d79671a772 +size 2097280 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-10dB/transmit/transmitwave.npy b/datasets/HiL-RED/barrage_narrow_jamming_-10dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-10dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-15dB/annotations/dense/202509082203273504/range_doppler.npy b/datasets/HiL-RED/barrage_narrow_jamming_-15dB/annotations/dense/202509082203273504/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..144fd555d765505d6732d5b553adb150822f5783 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-15dB/annotations/dense/202509082203273504/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a5c22060894811b53aac59e3d376dc3dc4785ec5c904a72ff00e82e7affa42c +size 131200 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-15dB/range_doppler_MTD/202509082203273504.npy b/datasets/HiL-RED/barrage_narrow_jamming_-15dB/range_doppler_MTD/202509082203273504.npy new file mode 100644 index 0000000000000000000000000000000000000000..4aa3e75e263e90ab5b7f33b01ec65d28567d877d --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-15dB/range_doppler_MTD/202509082203273504.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac0dd560deb14e3223b0b1f698e4ad46065fddaf0bd0c16e56bc1c08a9d79fc3 +size 2097280 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-15dB/range_doppler_echo/202509082203273504.npy b/datasets/HiL-RED/barrage_narrow_jamming_-15dB/range_doppler_echo/202509082203273504.npy new file mode 100644 index 0000000000000000000000000000000000000000..94432390d6225eff81e9eef0df81c2ec9f9f3987 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-15dB/range_doppler_echo/202509082203273504.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f87d2c4f27f413033e74750b2c16af2b83bf8e6c7e9836d2254fad8bd65e85f4 +size 2097280 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-15dB/transmit/transmitwave.npy b/datasets/HiL-RED/barrage_narrow_jamming_-15dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-15dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-20dB/annotations/dense/202509091239203879/range_doppler.npy b/datasets/HiL-RED/barrage_narrow_jamming_-20dB/annotations/dense/202509091239203879/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..e66e8fbe980a556ead88d29a4457eb29122f646f --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-20dB/annotations/dense/202509091239203879/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb4b727489e41156e4d1817f744735a31e30cf929b0df8991775160fc7443605 +size 131200 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-20dB/range_doppler_MTD/202509091239203879.npy b/datasets/HiL-RED/barrage_narrow_jamming_-20dB/range_doppler_MTD/202509091239203879.npy new file mode 100644 index 0000000000000000000000000000000000000000..00371f67fe26c8bcf0e54169c6cb45c1e741c3a8 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-20dB/range_doppler_MTD/202509091239203879.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:306bbb96aada7bc0356d5450dfab41c109d379d7760b5d85c7dcc9656ec82af8 +size 2097280 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-20dB/range_doppler_echo/202509091239203879.npy b/datasets/HiL-RED/barrage_narrow_jamming_-20dB/range_doppler_echo/202509091239203879.npy new file mode 100644 index 0000000000000000000000000000000000000000..f518193074d18513e66a13182e27617e91a49cfb --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-20dB/range_doppler_echo/202509091239203879.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08a8424908e2e8c0a77c127bbf2eabecee048dba654b99d2c823fdc271bd00bb +size 2097280 diff --git a/datasets/HiL-RED/barrage_narrow_jamming_-20dB/transmit/transmit/transmitwave.npy b/datasets/HiL-RED/barrage_narrow_jamming_-20dB/transmit/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/barrage_narrow_jamming_-20dB/transmit/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-10dB/annotations/dense/20250901111636100764/range_doppler.npy b/datasets/HiL-RED/barrage_wide_jamming_-10dB/annotations/dense/20250901111636100764/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..185f63840e4b7e04260b4c93e0fa22fef3bcb2ff --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-10dB/annotations/dense/20250901111636100764/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57d1db4de8704d4e8d1fdbca064efb95ddf8e49931228432b52e84c0f565fd46 +size 131200 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-10dB/range_doppler_MTD/20250901111636100764.npy b/datasets/HiL-RED/barrage_wide_jamming_-10dB/range_doppler_MTD/20250901111636100764.npy new file mode 100644 index 0000000000000000000000000000000000000000..2d493f3e4a12c0368537e274012bca06be42c62f --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-10dB/range_doppler_MTD/20250901111636100764.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5793d50ada7c56eefb74f33e99445522029366a4188552d29976299b0f3a1cf +size 2097280 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-10dB/range_doppler_echo/20250901111636100764.npy b/datasets/HiL-RED/barrage_wide_jamming_-10dB/range_doppler_echo/20250901111636100764.npy new file mode 100644 index 0000000000000000000000000000000000000000..5d278190bdc04705cc0560a69d2b2bf9df2ade90 --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-10dB/range_doppler_echo/20250901111636100764.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30510581ef1d25324aea4763eefa0ac88476b5edffebc154ab72ad5aa1821f30 +size 2097280 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-10dB/transmit/transmitwave.npy b/datasets/HiL-RED/barrage_wide_jamming_-10dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-10dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-15dB/annotations/dense/202509021530465441/range_doppler.npy b/datasets/HiL-RED/barrage_wide_jamming_-15dB/annotations/dense/202509021530465441/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..e6e52a105941d0bc394f9ae7190c88b88a9e5916 --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-15dB/annotations/dense/202509021530465441/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:faba94c0fa8d4fca54195167788ba40dfdb3217f15ae0c13776d0162d29dccbf +size 131200 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-15dB/range_doppler_MTD/202509021530465441.npy b/datasets/HiL-RED/barrage_wide_jamming_-15dB/range_doppler_MTD/202509021530465441.npy new file mode 100644 index 0000000000000000000000000000000000000000..8645087443f8544ab4019f7caf900abd1985fc6e --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-15dB/range_doppler_MTD/202509021530465441.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39c128493b83439b7d5a2525e6f16f4a4c2f43d511978c84f6b650a798b0b205 +size 2097280 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-15dB/range_doppler_echo/202509021530465441.npy b/datasets/HiL-RED/barrage_wide_jamming_-15dB/range_doppler_echo/202509021530465441.npy new file mode 100644 index 0000000000000000000000000000000000000000..357b0249d812ba101b9a69cc8c96c911309e60f0 --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-15dB/range_doppler_echo/202509021530465441.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1052c81c1985ed7f272c091bf3b5077f2f0351d3c54499af5b0163087097cf30 +size 2097280 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-15dB/transmit/transmitwave.npy b/datasets/HiL-RED/barrage_wide_jamming_-15dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-15dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-20dB/annotations/dense/202509031652503690/range_doppler.npy b/datasets/HiL-RED/barrage_wide_jamming_-20dB/annotations/dense/202509031652503690/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..95475cc5820acc26af5f6a6405c63c792026f26b --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-20dB/annotations/dense/202509031652503690/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86285a424c8d6fc828c492c7d6ae3a04f9ab9c224543207756a0a3cf03362135 +size 131200 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-20dB/range_doppler_MTD/202509031652503690.npy b/datasets/HiL-RED/barrage_wide_jamming_-20dB/range_doppler_MTD/202509031652503690.npy new file mode 100644 index 0000000000000000000000000000000000000000..1bbc492d19576f6ca0540a8bdc7a19c70f0fcceb --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-20dB/range_doppler_MTD/202509031652503690.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99fdb906b04ba369c849b1ff75d6888b912fe19fac37a6c8065f667584337fba +size 2097280 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-20dB/range_doppler_echo/202509031652503690.npy b/datasets/HiL-RED/barrage_wide_jamming_-20dB/range_doppler_echo/202509031652503690.npy new file mode 100644 index 0000000000000000000000000000000000000000..799f34830a08caf0cdd9cb9edc7e416019057a6c --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-20dB/range_doppler_echo/202509031652503690.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a7259c589bdb9fc075a2374bf6b38317e64d96210d9737add52f97f127ff61e +size 2097280 diff --git a/datasets/HiL-RED/barrage_wide_jamming_-20dB/transmit/transmitwave.npy b/datasets/HiL-RED/barrage_wide_jamming_-20dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/barrage_wide_jamming_-20dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/coefs/s_tx.mat b/datasets/HiL-RED/coefs/s_tx.mat new file mode 100644 index 0000000000000000000000000000000000000000..bf06480cd7258467223718664b7e1246047f0a8d Binary files /dev/null and b/datasets/HiL-RED/coefs/s_tx.mat differ diff --git a/datasets/HiL-RED/coefs/w_blackman.mat b/datasets/HiL-RED/coefs/w_blackman.mat new file mode 100644 index 0000000000000000000000000000000000000000..1f647a7053b54700c6f89c38f58b28e357748742 Binary files /dev/null and b/datasets/HiL-RED/coefs/w_blackman.mat differ diff --git a/datasets/HiL-RED/coefs/w_chebyshev.mat b/datasets/HiL-RED/coefs/w_chebyshev.mat new file mode 100644 index 0000000000000000000000000000000000000000..d50b8e679d2f576b3b4aed80577a16d32221763b Binary files /dev/null and b/datasets/HiL-RED/coefs/w_chebyshev.mat differ diff --git a/datasets/HiL-RED/coefs/w_cosine.mat b/datasets/HiL-RED/coefs/w_cosine.mat new file mode 100644 index 0000000000000000000000000000000000000000..0cac0aa55926f5778b24e758043de54a716b135e Binary files /dev/null and b/datasets/HiL-RED/coefs/w_cosine.mat differ diff --git a/datasets/HiL-RED/coefs/w_hamming.mat b/datasets/HiL-RED/coefs/w_hamming.mat new file mode 100644 index 0000000000000000000000000000000000000000..992f51aefa4478a67c0f4bcced2f08a7cc122a60 Binary files /dev/null and b/datasets/HiL-RED/coefs/w_hamming.mat differ diff --git a/datasets/HiL-RED/coefs/w_hanning.mat b/datasets/HiL-RED/coefs/w_hanning.mat new file mode 100644 index 0000000000000000000000000000000000000000..c873b1a1a9d24992f800bf90dca661509d6c2b0e Binary files /dev/null and b/datasets/HiL-RED/coefs/w_hanning.mat differ diff --git a/datasets/HiL-RED/coefs/w_rectangular.mat b/datasets/HiL-RED/coefs/w_rectangular.mat new file mode 100644 index 0000000000000000000000000000000000000000..9cc1575168b4a09e027ffcc14364deae78ca1a48 Binary files /dev/null and b/datasets/HiL-RED/coefs/w_rectangular.mat differ diff --git a/datasets/HiL-RED/coefs/w_taylor.mat b/datasets/HiL-RED/coefs/w_taylor.mat new file mode 100644 index 0000000000000000000000000000000000000000..da68522477d6f0b48765420fe9fc9ac598d32b3b Binary files /dev/null and b/datasets/HiL-RED/coefs/w_taylor.mat differ diff --git a/datasets/HiL-RED/data_seq_ref.json b/datasets/HiL-RED/data_seq_ref.json new file mode 100644 index 0000000000000000000000000000000000000000..6c123d39a8a0770a618b55f570233200f9955caf --- /dev/null +++ b/datasets/HiL-RED/data_seq_ref.json @@ -0,0 +1,107 @@ +{ + "deceptive_sli_jammer_-15dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "deceptive_sli_jammer_-20dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "deceptive_dft_jammer_-10dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "deceptive_isr_jammer_-15dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "barrage_wide_jamming_-10dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "deceptive_isr_jammer_-20dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "deceptive_dft_jammer_-15dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "barrage_narrow_jamming_-10dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "barrage_narrow_jamming_-15dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "barrage_wide_jamming_-20dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "deceptive_dft_jammer_-20dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "barrage_narrow_jamming_-20dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "deceptive_sli_jammer_-10dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "barrage_wide_jamming_-15dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + }, + "deceptive_isr_jammer_-10dB": { + "split": [ + "Train", + "Validation", + "Test" + ] + } +} \ No newline at end of file diff --git a/datasets/HiL-RED/dataset_meta.json b/datasets/HiL-RED/dataset_meta.json new file mode 100644 index 0000000000000000000000000000000000000000..ec333842420cbaa65bfb6500301cb77f9389283e --- /dev/null +++ b/datasets/HiL-RED/dataset_meta.json @@ -0,0 +1,9 @@ +{ + "display_name": "HiL-RED", + "full_name": "Hardware-in-the-Loop Radar Echo Dataset", + "scenario": "Target-jammer recognition under active electronic countermeasures", + "order": 2, + "mtd_fftshift": true, + "mtd_amp_dir": "range_doppler_MTD", + "valid_classes": [0, 1, 2, 3, 4, 5, 6] +} diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-10dB/annotations/dense/202509092208275264/range_doppler.npy b/datasets/HiL-RED/deceptive_dft_jammer_-10dB/annotations/dense/202509092208275264/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..451b42372db3ee30d11d4833754f61b5f1733b2b --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-10dB/annotations/dense/202509092208275264/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7b4beedcd2f094ca06da5f5834f47024358a3ad10e7f13216d3c702314afd36 +size 131200 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-10dB/range_doppler_MTD/202509092208275264.npy b/datasets/HiL-RED/deceptive_dft_jammer_-10dB/range_doppler_MTD/202509092208275264.npy new file mode 100644 index 0000000000000000000000000000000000000000..479ea8406521480317e789d950a161038fb0a913 --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-10dB/range_doppler_MTD/202509092208275264.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fc43c56366f3e99a3891d9e5e1939211cfecbf9a393db7acc1e5011f921546c +size 2097280 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-10dB/range_doppler_echo/202509092208275264.npy b/datasets/HiL-RED/deceptive_dft_jammer_-10dB/range_doppler_echo/202509092208275264.npy new file mode 100644 index 0000000000000000000000000000000000000000..f30ad2c38851e3a786ec81ba6295f1a263b7afca --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-10dB/range_doppler_echo/202509092208275264.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:983852934cdd8eeafe1b1653d35e51f2745fdf835ef33b42816b9625f5fc2b5b +size 2097280 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-10dB/transmit/transmitwave.npy b/datasets/HiL-RED/deceptive_dft_jammer_-10dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-10dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-15dB/annotations/dense/202509102013124057/range_doppler.npy b/datasets/HiL-RED/deceptive_dft_jammer_-15dB/annotations/dense/202509102013124057/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..df30605410646a8449ab4426c8fe11ef49d4d0cb --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-15dB/annotations/dense/202509102013124057/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52a1e70875b5d32ed657ea0414a4cb2736136b7837cf919c51dbfb58fbe36937 +size 131200 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-15dB/range_doppler_MTD/202509102013124057.npy b/datasets/HiL-RED/deceptive_dft_jammer_-15dB/range_doppler_MTD/202509102013124057.npy new file mode 100644 index 0000000000000000000000000000000000000000..aa481b871a59ee0fb97066cbb8c4ef383081c1f3 --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-15dB/range_doppler_MTD/202509102013124057.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a020d43a63d006c93a472a7217a6a21591002c57fca058decc3ea530e6dfd8e4 +size 2097280 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-15dB/range_doppler_echo/202509102013124057.npy b/datasets/HiL-RED/deceptive_dft_jammer_-15dB/range_doppler_echo/202509102013124057.npy new file mode 100644 index 0000000000000000000000000000000000000000..bd435417a19b8d3833a4c05aad4eee3e4c82367f --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-15dB/range_doppler_echo/202509102013124057.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84fd1398de71cdce4cd8ca65d2c7acd8055eb62c9a0a5fa85b59328b53c8bb4d +size 2097280 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-15dB/transmit/transmitwave.npy b/datasets/HiL-RED/deceptive_dft_jammer_-15dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-15dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-20dB/annotations/dense/202509112218344171/range_doppler.npy b/datasets/HiL-RED/deceptive_dft_jammer_-20dB/annotations/dense/202509112218344171/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..f0e247d005d1eae72246439b0c37039b174dbd6e --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-20dB/annotations/dense/202509112218344171/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:721dad995d4d8bd62abf8b30ed566546b90d24016c70fb99ffb37724871395bc +size 131200 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-20dB/range_doppler_MTD/202509112218344171.npy b/datasets/HiL-RED/deceptive_dft_jammer_-20dB/range_doppler_MTD/202509112218344171.npy new file mode 100644 index 0000000000000000000000000000000000000000..bf28be0a86476a7c55ba958d281d5fb2c0840841 --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-20dB/range_doppler_MTD/202509112218344171.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81f258c2b7d3a184882af14848de3d7c22edddeef07ee9f60e6b185bd39ef1c3 +size 2097280 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-20dB/range_doppler_echo/202509112218344171.npy b/datasets/HiL-RED/deceptive_dft_jammer_-20dB/range_doppler_echo/202509112218344171.npy new file mode 100644 index 0000000000000000000000000000000000000000..628c8b200c8f839a69477a5aa49481b90cc0e766 --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-20dB/range_doppler_echo/202509112218344171.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b628d5ed5f974eacb1708ad4ed37f66930c4766a847d6d4ff3b6365f0090fec8 +size 2097280 diff --git a/datasets/HiL-RED/deceptive_dft_jammer_-20dB/transmit/transmitwave.npy b/datasets/HiL-RED/deceptive_dft_jammer_-20dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/deceptive_dft_jammer_-20dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-10dB/annotations/dense/202509121322404022/range_doppler.npy b/datasets/HiL-RED/deceptive_isr_jammer_-10dB/annotations/dense/202509121322404022/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..877f6bc1c083eb2055d8fd3c83979c73e4d5d565 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-10dB/annotations/dense/202509121322404022/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8573a822a4cf34860e61c1dda1f1fc709a77d736e40aa2770de9de83fec322d7 +size 131200 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-10dB/range_doppler_MTD/202509121322404022.npy b/datasets/HiL-RED/deceptive_isr_jammer_-10dB/range_doppler_MTD/202509121322404022.npy new file mode 100644 index 0000000000000000000000000000000000000000..a26df225499dc9b997cd313cfd62ab35060c7856 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-10dB/range_doppler_MTD/202509121322404022.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9961403d50d707eaed003c5ad68dcb79e582353e56e975b6f95e4cb5434d390b +size 2097280 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-10dB/range_doppler_echo/202509121322404022.npy b/datasets/HiL-RED/deceptive_isr_jammer_-10dB/range_doppler_echo/202509121322404022.npy new file mode 100644 index 0000000000000000000000000000000000000000..63875e6a48a62f50c0ed892fc7fa3451645480d4 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-10dB/range_doppler_echo/202509121322404022.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8ebeb65fd8354babc611b210dc83bac9d1505ad3c55d86eb3f8533e2e74555b +size 2097280 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-10dB/transmit/transmitwave.npy b/datasets/HiL-RED/deceptive_isr_jammer_-10dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-10dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-15dB/annotations/dense/202509122330044379/range_doppler.npy b/datasets/HiL-RED/deceptive_isr_jammer_-15dB/annotations/dense/202509122330044379/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..08b58f533921b281037f507f6f0106a2a9ff7e1c --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-15dB/annotations/dense/202509122330044379/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af446c2ce57704fa9aee5040e0232092eda5400c6c4cc14a1f0d167c2e8fe943 +size 131200 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-15dB/range_doppler_MTD/202509122330044379.npy b/datasets/HiL-RED/deceptive_isr_jammer_-15dB/range_doppler_MTD/202509122330044379.npy new file mode 100644 index 0000000000000000000000000000000000000000..91321f9d31132863d4cdd23bf634216841190c76 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-15dB/range_doppler_MTD/202509122330044379.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e28299be061da2f5f3e3926be1b2a774f032a0c5dd0db67c73074d0d217f3c62 +size 2097280 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-15dB/range_doppler_echo/202509122330044379.npy b/datasets/HiL-RED/deceptive_isr_jammer_-15dB/range_doppler_echo/202509122330044379.npy new file mode 100644 index 0000000000000000000000000000000000000000..6edd966625d88e338ff3fc601d788fed4681cbe1 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-15dB/range_doppler_echo/202509122330044379.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:890409ced4d957839eb31b026d472d91d62bc034a822e62ed4eb24fe43183b0d +size 2097280 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-15dB/transmit/transmitwave.npy b/datasets/HiL-RED/deceptive_isr_jammer_-15dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-15dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-20dB/annotations/dense/202509151757054278/range_doppler.npy b/datasets/HiL-RED/deceptive_isr_jammer_-20dB/annotations/dense/202509151757054278/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..603cf420e97c0ab7672961a9b14ec17bb0636aeb --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-20dB/annotations/dense/202509151757054278/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d540c1365988a4f8a614b362a8a016de073f6ebbfe27b0b61dce1384ffb2708a +size 131200 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-20dB/range_doppler_MTD/202509151757054278.npy b/datasets/HiL-RED/deceptive_isr_jammer_-20dB/range_doppler_MTD/202509151757054278.npy new file mode 100644 index 0000000000000000000000000000000000000000..c4a9baa1ea1714740cd3918d4d35b82e0ec1c3f6 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-20dB/range_doppler_MTD/202509151757054278.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95358b46c1792e7b6ce85dc1e9bfd3dc8bb5e041794421408aeec36048d97a59 +size 2097280 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-20dB/range_doppler_echo/202509151757054278.npy b/datasets/HiL-RED/deceptive_isr_jammer_-20dB/range_doppler_echo/202509151757054278.npy new file mode 100644 index 0000000000000000000000000000000000000000..33dbb96fde1328898528ab6aa656b95652957fe3 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-20dB/range_doppler_echo/202509151757054278.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d6c3d7633f743062dbbd6032724e8bcc1ac8f9d647b9401096d97a47a2d6a0a +size 2097280 diff --git a/datasets/HiL-RED/deceptive_isr_jammer_-20dB/transmit/transmitwave.npy b/datasets/HiL-RED/deceptive_isr_jammer_-20dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/deceptive_isr_jammer_-20dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-10dB/annotations/dense/202509160330105009/range_doppler.npy b/datasets/HiL-RED/deceptive_sli_jammer_-10dB/annotations/dense/202509160330105009/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..e2b43df4241c3fc977aae0bebc2684bf745a70d5 --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-10dB/annotations/dense/202509160330105009/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c5a595e063a2cbcd024b83aab7bcf81dfaf03050b00f7afa95e268005f72bdd +size 131200 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-10dB/range_doppler_MTD/202509160330105009.npy b/datasets/HiL-RED/deceptive_sli_jammer_-10dB/range_doppler_MTD/202509160330105009.npy new file mode 100644 index 0000000000000000000000000000000000000000..10410174e6e7c36ce051275627f593bd2b1eeb52 --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-10dB/range_doppler_MTD/202509160330105009.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4bd1bd04ac6075c638e10b11dae332414baaadee1800d7094ce7d65682ee9e88 +size 2097280 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-10dB/range_doppler_echo/202509160330105009.npy b/datasets/HiL-RED/deceptive_sli_jammer_-10dB/range_doppler_echo/202509160330105009.npy new file mode 100644 index 0000000000000000000000000000000000000000..a63f1a34f9866a41d6ed859ee633eacd6a763093 --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-10dB/range_doppler_echo/202509160330105009.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f556aaf2be6e4e5d0b3f1ab7f10d3256e47470bc63084e4769b1a02118f647a +size 2097280 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-10dB/transmit/transmitwave.npy b/datasets/HiL-RED/deceptive_sli_jammer_-10dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-10dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-15dB/annotations/dense/202509170155574228/range_doppler.npy b/datasets/HiL-RED/deceptive_sli_jammer_-15dB/annotations/dense/202509170155574228/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..83e0aff4969192d1b30662c2d4aed7d357dcbdb9 --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-15dB/annotations/dense/202509170155574228/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e4b1f7fe1be094b6c1abe9b907d42fba01941e7539d35dfd0eeea0612aa0ddf +size 131200 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-15dB/range_doppler_MTD/202509170155574228.npy b/datasets/HiL-RED/deceptive_sli_jammer_-15dB/range_doppler_MTD/202509170155574228.npy new file mode 100644 index 0000000000000000000000000000000000000000..d41d49de0d87d0cfc7356943b24328ceffa82635 --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-15dB/range_doppler_MTD/202509170155574228.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1afa42e443c1e5ec9d976e4be1276707d640faad7ed946282f6051a960503895 +size 2097280 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-15dB/range_doppler_echo/202509170155574228.npy b/datasets/HiL-RED/deceptive_sli_jammer_-15dB/range_doppler_echo/202509170155574228.npy new file mode 100644 index 0000000000000000000000000000000000000000..eddafa74a974594003ae3b27e3c3ca58fed087dc --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-15dB/range_doppler_echo/202509170155574228.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cc6282ee9b779c38c0e6ca02a18c7a6a38137dbf96ab9a7a8a631cded9c5b0e +size 2097280 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-20dB/annotations/dense/202509241610546885/range_doppler.npy b/datasets/HiL-RED/deceptive_sli_jammer_-20dB/annotations/dense/202509241610546885/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..2ad7c5517d3341d023b84a81fd03257ac90015b8 --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-20dB/annotations/dense/202509241610546885/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b79531f5d55f912e265e9abdd8f97627a1f8054d348a7a6ea00fdc28b8d3d9cb +size 131200 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-20dB/range_doppler_MTD/202509241610546885.npy b/datasets/HiL-RED/deceptive_sli_jammer_-20dB/range_doppler_MTD/202509241610546885.npy new file mode 100644 index 0000000000000000000000000000000000000000..bdda48e54ab3a7ca8e740276278f5e9f70b565cd --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-20dB/range_doppler_MTD/202509241610546885.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f59d6b2a5f6d469c18c07c9703402bc197cbffd1cb6a7a8ebeae1025db3f90f2 +size 2097280 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-20dB/range_doppler_echo/202509241610546885.npy b/datasets/HiL-RED/deceptive_sli_jammer_-20dB/range_doppler_echo/202509241610546885.npy new file mode 100644 index 0000000000000000000000000000000000000000..c63344d6528fc7da0f7e7585bc6670edeeebe50e --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-20dB/range_doppler_echo/202509241610546885.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34af136f84ce1cc4226eb771c093d5aa537050ff2b5ffc40fae2730eb93eea5f +size 2097280 diff --git a/datasets/HiL-RED/deceptive_sli_jammer_-20dB/transmit/transmitwave.npy b/datasets/HiL-RED/deceptive_sli_jammer_-20dB/transmit/transmitwave.npy new file mode 100644 index 0000000000000000000000000000000000000000..eeafa2357d30f1d06893ebea77ce93526fff2786 --- /dev/null +++ b/datasets/HiL-RED/deceptive_sli_jammer_-20dB/transmit/transmitwave.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a116b381caa9593aba463f8b2052a9a697847ed712500926f0a87e5c5f846695 +size 6528 diff --git a/datasets/HiL-RED/light_dataset_frame_oriented.json b/datasets/HiL-RED/light_dataset_frame_oriented.json new file mode 100644 index 0000000000000000000000000000000000000000..8e87a54f795e6b21525feb3291e4f5337a3bc540 --- /dev/null +++ b/datasets/HiL-RED/light_dataset_frame_oriented.json @@ -0,0 +1,47 @@ +{ + "barrage_narrow_jamming_-10dB": [ + "2025090809332621314" + ], + "barrage_narrow_jamming_-15dB": [ + "202509082203273504" + ], + "barrage_narrow_jamming_-20dB": [ + "202509091239203879" + ], + "barrage_wide_jamming_-10dB": [ + "20250901111636100764" + ], + "barrage_wide_jamming_-15dB": [ + "202509021530465441" + ], + "barrage_wide_jamming_-20dB": [ + "202509031652503690" + ], + "deceptive_dft_jammer_-10dB": [ + "202509092208275264" + ], + "deceptive_dft_jammer_-15dB": [ + "202509102013124057" + ], + "deceptive_dft_jammer_-20dB": [ + "202509112218344171" + ], + "deceptive_isr_jammer_-10dB": [ + "202509121322404022" + ], + "deceptive_isr_jammer_-15dB": [ + "202509122330044379" + ], + "deceptive_isr_jammer_-20dB": [ + "202509151757054278" + ], + "deceptive_sli_jammer_-10dB": [ + "202509160330105009" + ], + "deceptive_sli_jammer_-15dB": [ + "202509170155574228" + ], + "deceptive_sli_jammer_-20dB": [ + "202509241610546885" + ] +} \ No newline at end of file diff --git a/datasets/Syn-RED/coefs/s_tx.mat b/datasets/Syn-RED/coefs/s_tx.mat new file mode 100644 index 0000000000000000000000000000000000000000..c0076e2944f06b66d2198fcc49e1c14525a56310 Binary files /dev/null and b/datasets/Syn-RED/coefs/s_tx.mat differ diff --git a/datasets/Syn-RED/coefs/w_blackman.mat b/datasets/Syn-RED/coefs/w_blackman.mat new file mode 100644 index 0000000000000000000000000000000000000000..77cb565d59a66649440ca3028281eb0f41394685 Binary files /dev/null and b/datasets/Syn-RED/coefs/w_blackman.mat differ diff --git a/datasets/Syn-RED/coefs/w_chebyshev.mat b/datasets/Syn-RED/coefs/w_chebyshev.mat new file mode 100644 index 0000000000000000000000000000000000000000..9950b8d6b3d9f5c288a047bb02d5583be1a9aa71 Binary files /dev/null and b/datasets/Syn-RED/coefs/w_chebyshev.mat differ diff --git a/datasets/Syn-RED/coefs/w_cosine.mat b/datasets/Syn-RED/coefs/w_cosine.mat new file mode 100644 index 0000000000000000000000000000000000000000..6a654df2a072f30932b2c0b2362f766c3ecbb47f Binary files /dev/null and b/datasets/Syn-RED/coefs/w_cosine.mat differ diff --git a/datasets/Syn-RED/coefs/w_hamming.mat b/datasets/Syn-RED/coefs/w_hamming.mat new file mode 100644 index 0000000000000000000000000000000000000000..e9226084a1f5e340d1f371c94a5820a75076ad2e Binary files /dev/null and b/datasets/Syn-RED/coefs/w_hamming.mat differ diff --git a/datasets/Syn-RED/coefs/w_hanning.mat b/datasets/Syn-RED/coefs/w_hanning.mat new file mode 100644 index 0000000000000000000000000000000000000000..f3bee267ed012e260b33404abdecb64bfac853a2 Binary files /dev/null and b/datasets/Syn-RED/coefs/w_hanning.mat differ diff --git a/datasets/Syn-RED/coefs/w_rectangular.mat b/datasets/Syn-RED/coefs/w_rectangular.mat new file mode 100644 index 0000000000000000000000000000000000000000..45d3819a7d1ac6276e42b12666551e6c6ecaa9da Binary files /dev/null and b/datasets/Syn-RED/coefs/w_rectangular.mat differ diff --git a/datasets/Syn-RED/coefs/w_taylor.mat b/datasets/Syn-RED/coefs/w_taylor.mat new file mode 100644 index 0000000000000000000000000000000000000000..f2a28350b99ef26cb426d5be6394ad431062a9ff Binary files /dev/null and b/datasets/Syn-RED/coefs/w_taylor.mat differ diff --git a/datasets/Syn-RED/data_1000m_Hover_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_Hover_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..4e9e0805ac6937b35c0a835f886a5373b82c6fe7 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a479807a131c33c1160c9433345b177166a23b4197738f3b25365195f31d691e +size 262272 diff --git a/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..32507df72aff9884ef54608f27c905a4a606f87e --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b033d970b6dbdde858c0d61bfa5fa66cef3502db653af15c1c029b30dc2cdec2 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..99f7cc6901d652cb082666fe3b52c5699655f3fa --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e8c84b20954de66f50dfdebdc6372220c4121cc15e9d67419fc0beb992d7fe7 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a20314efd7775d92ea917a7f2e13fb13cf536647 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:814cd22cc5188eaad04d5e42cb4b16a4e9b8f0312b0e27c13dc4da490a4631a6 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_Hover_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_Hover_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..4e9e0805ac6937b35c0a835f886a5373b82c6fe7 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a479807a131c33c1160c9433345b177166a23b4197738f3b25365195f31d691e +size 262272 diff --git a/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..7ecc359dea5a6c36f60720de015cd5dde37aebbf --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:678a790a5e0fe9c55208dca3c0c203613c7a62ed3306a1ac3c653046d63049c1 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..de3af06ed37b4ee360bfb14653efaf1b95345ab5 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3c1ce39f3ebc9018226f79e74cc5697e4fe9257281296a7554b460bca698f81 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..2e90206857baf4df8ee28288d7a8e7b9cfa00dbb --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a83c6e4ffe152fc6ba82e2721d63ac66b6616f9e76cf6bc911ce381de1631a1 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_Hover_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_Hover_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..4e9e0805ac6937b35c0a835f886a5373b82c6fe7 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a479807a131c33c1160c9433345b177166a23b4197738f3b25365195f31d691e +size 262272 diff --git a/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a796b9a4f2835c9d640cbced035f2ee2a16855bd --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0d68f13fcbc16788043fffae5624415d8d3271eb2fd0896550eebcf4f9cbc40 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..72e15f995814b38b76ad477a865fa1a524278817 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:887c67f11280df7c0206fc3a6a181b2c96d04c215c9d36efadd50f663d4cbceb +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..370043ad20264a50c3ce2c93048b3f397e431a0b --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94de4e77abfd8f26bd6b7dc79cb0351787d7ecfc2300295e0a5eeafde7e869c0 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_Line_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_Line_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..8dc8b692db9b94b80f209d4496524ceca47d24d0 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c85fc30cae01deb96f0b1da1534ad50f1dceebfa7bda431808a6929e8c6403bd +size 262272 diff --git a/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a19b9586978710f2bd1b393ac5ee02ae83649c49 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6311deb43dc32dfcdf46ec406d785784477bd2f16f36497ff71c441060b3be5b +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..76dfd28f5d93a0aaa0c056a7d4aa84503c0e19c4 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ccd4377dbf201626fbf87c7d4012d45ab64ab3137c7c18d8c615ec3be6fec01 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..adb1730b78793dca4e99b70150ea01980cca7d0e --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dea6449b39ed9d522f1393223ac30591f53adfc4c5eaf287965c3f690a0fd411 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_Line_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_Line_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..8dc8b692db9b94b80f209d4496524ceca47d24d0 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c85fc30cae01deb96f0b1da1534ad50f1dceebfa7bda431808a6929e8c6403bd +size 262272 diff --git a/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..6fa83c9bb31f16a745b325024a2d14d002c0d2e2 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e99c3d2009eb076684c5ae0b4e4f2eef2194bc465e441910b1ba56d4e5d26d8 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a9aa0f59f66ce230f926a002d4816a91fb327709 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1908a104e3a40904ab6db6c0770eabed460eb1dbd1b72ebf4848efd46070e5ce +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..85d7e585df3e3609fd80b6c8733ae13a17ef2efb --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f3a6ce4fc61f410371bd2958e1427d7635f112f1aa5b6458c924f32c03320f9 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_Line_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_Line_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..8dc8b692db9b94b80f209d4496524ceca47d24d0 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c85fc30cae01deb96f0b1da1534ad50f1dceebfa7bda431808a6929e8c6403bd +size 262272 diff --git a/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..16925f1f21da7b640da1bf859c0db11884a69b5d --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14899d1db119004490ce7f4deef4ea3918258a5e21163a0f36b80a4118a3e1e8 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..12c58d5e973054ed0ad9f97d0a0dc6bba9e8fcd0 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88b7f7a793074964b67857e6dce4460b821e43ff5c871f0aa7afe385a96d0c54 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..bfecd4cae333c437a4e0d4d93a43f35616bedb10 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_Line_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:838384235dec34112e718f90b1da9a8d4c31529579bb9ba3c118b61f019962c2 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_O_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_O_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..4e9e0805ac6937b35c0a835f886a5373b82c6fe7 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a479807a131c33c1160c9433345b177166a23b4197738f3b25365195f31d691e +size 262272 diff --git a/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..218a2ba95dbf0d5ef9e8304bcf0600ee8351f5c9 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:162ad546c61410f6f09b074723a0dadcc1d0c1160b7e299d4113c3195598d47b +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..f441aca43b7f709d27ef662f4df17a78381c3c04 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9842f3c9fd8518820101e9e298f9b66baf84de9d5de5c365ddc5a6e32c17c775 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..b68b7de06306f18b83f83f1a98b75be8ebf47ebe --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e2b484b95482c283198ae8045fa488a5f26e17651d638fbc15ddbe8ea1a9cf8 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_O_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_O_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..4e9e0805ac6937b35c0a835f886a5373b82c6fe7 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a479807a131c33c1160c9433345b177166a23b4197738f3b25365195f31d691e +size 262272 diff --git a/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a5c0edf781fa85f89ed7923a5a5e2232bb93815b --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81fec8af7a879a1b2681dac0fdb59f1a6bb085410420d326abb5188c7968bfc6 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..297d16c4563cddeb5be35e923b12153aa32ab11c --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03f6d854aa2ee1c174eb5f949787f8b1988dc42696fe678bb036aa5eae155dc4 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..3979f12e90004aa22e8c9ecee0d08573cf26b1e2 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7283d8078b1dfb72f8b8b45f884a0e47241e532037c1dc97abf332655eed4cbc +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_O_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_O_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..4e9e0805ac6937b35c0a835f886a5373b82c6fe7 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a479807a131c33c1160c9433345b177166a23b4197738f3b25365195f31d691e +size 262272 diff --git a/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..8ea00890ef5a26052a58180c0a22d33c699e3da7 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f5737a10c957d1d8201ccb4696b0217682b35a899426becb60d6934c93008f4f +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..80a9efdd4595f4c2a713bba74c59a62413488cdd --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa72f384e2a325fe68a350017def7d158c7ced6d2f1ce1d40f22dce7c324b38a +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..f3b2cc8c0ce8fd37333138cb958240efb6399438 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_O_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3b931dacd39408f957473a1540209583c1507c3f92c4030d11b0a2303cc3bb6 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_S_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_S_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..8dc8b692db9b94b80f209d4496524ceca47d24d0 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c85fc30cae01deb96f0b1da1534ad50f1dceebfa7bda431808a6929e8c6403bd +size 262272 diff --git a/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..18a7533d1dd4605f29809f01968ab49e806891e0 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1753fabc64e8bafdeb2a41e8d959f4f2782a22db1db18a432d1cf429826c9ea +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..7296765cee9c387ec66973d245f55ff1b8b2658e --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:952db0136e175926c72f2e94c6e28419fddd315d5009a53801a2bec069862546 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a17cb5a055b0ced380b91f50bbcf4facfdb9c7a6 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12df8f05dd38722bf9e62c8800993c6f58c52866d2d2adb753dea73b1b28a920 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_S_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_S_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..8dc8b692db9b94b80f209d4496524ceca47d24d0 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c85fc30cae01deb96f0b1da1534ad50f1dceebfa7bda431808a6929e8c6403bd +size 262272 diff --git a/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..358584d5ac0a5601b39eb9b522aae6ac1d8e313e --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da38c185b34a7c60c94126101057a2d299b975a1d5e8d4b2e5c2181115365e08 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..7b088504b527f63997c8f530fbc62a9341345474 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fc2fc4b71187395becd33c378da80080b19000653a5bbdfda624bc3ab8cfe64 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..5473db02b17a5b71eff69677f210108a06487301 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a73f6d5b2a7d8200566772311485a776a43e6c7bcc6c9569170858ce4a83a11 +size 1048704 diff --git a/datasets/Syn-RED/data_1000m_S_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_1000m_S_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..8dc8b692db9b94b80f209d4496524ceca47d24d0 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c85fc30cae01deb96f0b1da1534ad50f1dceebfa7bda431808a6929e8c6403bd +size 262272 diff --git a/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..52be22f280d074a0c62e9d4e19da5f7411e51284 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85fd92d7b62c2dac9c9dd1fbe0236213efe8aa4c9a8bb601134ddf463de13ebd +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..5b10029f17b28a67f7475b77ee886fc969178c66 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:569d46c565cefbd3f63cdeb289f393c1573c9299b4ea0d4a767cb4d295b8d4d6 +size 2097280 diff --git a/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a65786620f5ef4830698e3f32c0c88ebaa81eac5 --- /dev/null +++ b/datasets/Syn-RED/data_1000m_S_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:333f2d475d3a86d1ca4a8f5f688f450c06c81504e42380d1f23d28030dd5de91 +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_Hover_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_Hover_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..697459d56fe9046ef54870f14e8a0e1a10aad8fa --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4606564540f6059f62fb8cb9d95a778f813839b4abeeba54857ad5b22750cdb +size 262272 diff --git a/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..e6e188d7efd8ad94e108cb4dc1e8d2395be76eee --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5dc476db5dcad49d87795192f71b44112b3b1160a02e46140c465c5e16cb42b8 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..2054023da86d8b95c5b7076094977b13f20a1b78 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71d75e0b989ce3725b8fb65a7711bcd94802a45b474402ffaa8c18ca64bb940f +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..3813c765780ae642c5d6cad4578debb0d8a4b7d5 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b0b8a25343792c18d3553eb6c710c8dd186556a1433aa3068179fa553b89c8b +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_Hover_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_Hover_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..697459d56fe9046ef54870f14e8a0e1a10aad8fa --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4606564540f6059f62fb8cb9d95a778f813839b4abeeba54857ad5b22750cdb +size 262272 diff --git a/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..64d8eea620f3f995bbea04afead9ebac07e58219 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d6c3e37b078e45f3fa9a6ab4245f0a244883ddc53090c6bcab06e9514b3a5ff +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..75d48e822a0810429375fc3bede2704f7bafb59e --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6950edd16ad91b807c50d5235282a8abd0e8b239b0b03613220a9863494040c8 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..bd83dc4c15844ea33bdd094393148d7ff873db63 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b345b3be931ec72d5d03c7da1152e87038c913eb287fce6e90aa1719a05c0b64 +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_Hover_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_Hover_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..697459d56fe9046ef54870f14e8a0e1a10aad8fa --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4606564540f6059f62fb8cb9d95a778f813839b4abeeba54857ad5b22750cdb +size 262272 diff --git a/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..afb17dc2709ee2dfa53b86ddd3ea2f7ff79619d9 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21c7d4506a03f2eed3547f489b74bceb269960cab8eb7421c63285e88bef45d3 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..f430d27662095bfd976f626dc7a2671e98f26629 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4edd3c5d09ccae973d2e4706959a824c68f23565fa89cc82bd3a5c3770193040 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..0ad7c4c1b43280e9a4263a3d049d33837d184e38 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:adfae0fcd3ba75a2a222f7fd5b6e1ca3f984d314fcf608d2f1950ed136be3e9a +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_Line_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_Line_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..06ab9840bf9b7f1f4f6842b920ef7e39ffa6f0a7 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88d12a6706e9f755ac19e1ab36e707e88a722330504609f541b605b024d31c4f +size 262272 diff --git a/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..aeb13c9d9485dd06790ba5fc08f7633eae2be6b6 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4ba8a3ffd6c3ec0d4644614771374c2947d9f7fd0e99fb44a49e2e86df430c4 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..c97cc8d0d7b5241b01f70809eb1c7ecbdfd799c6 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97ab43ec4107ef386435aa6eb566db4d13521f2db81ba1debf7c5031f7212189 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..dae2f6e9580616038fe214eed4a40d98755b6936 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f90e34b903a9964f9063078ca8dc0c9d7a48ab6552a56edb08b3a619a7bdb74 +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_Line_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_Line_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..06ab9840bf9b7f1f4f6842b920ef7e39ffa6f0a7 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88d12a6706e9f755ac19e1ab36e707e88a722330504609f541b605b024d31c4f +size 262272 diff --git a/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..4e61e7027ef1db54bbfa692ab784ab9123cbceb2 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc6c0df273d6545d0ca704725ce9a6654c484ea82fb4dee2e710578a56dbf550 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a49044962583913dab5c1d39cedc97c74f68705b --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74dfe6eaf1351cd4539351694afa6b57500a232898e9e7fe6f6e8765e1cb013f +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..32d4c3e3153c537944dab5ce3b78a85dd4615bb2 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ba511defd065285d3f4edcbf086888fc9bab657c7fe1e0bc544fbc7221c6dc2 +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_Line_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_Line_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..06ab9840bf9b7f1f4f6842b920ef7e39ffa6f0a7 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88d12a6706e9f755ac19e1ab36e707e88a722330504609f541b605b024d31c4f +size 262272 diff --git a/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..389deb0bba0040ccb8879abfe4eaabc21e0f08f0 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:537a31204419689f620425f89fd8ad885c004e452065bab3fa3655d18012795a +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..8bd2e12021b06d64a2e954115c4c0baba3c760e7 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a07f18707e15d7cedf6183969848bbf1b105062e64133c83fc1477bbdc1f94af +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..e801ed4db9f93b09d33e85bbea09062e5637b650 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_Line_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0dc2f1bff052d5503b5a3d245311aa1ccd0c2bbf0f06b623f264d37398e823e7 +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_O_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_O_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..697459d56fe9046ef54870f14e8a0e1a10aad8fa --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4606564540f6059f62fb8cb9d95a778f813839b4abeeba54857ad5b22750cdb +size 262272 diff --git a/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..6977496eefc187c2ec788c93a6be8ee98783479c --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a704e164c859fec729d67e376bcc60c1889f7251609b554120bc4215277d87b +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..41fdd3a4e68e3e0a7524ad43699e9bea0e426f22 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3d231dbe2f6e6eddfe3eb980f43b305ebbf12b88828d1f436a86fe37f084543 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..063cc339be73ec6b02074f6440a356dd7f7fbf91 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63bffb65e9d69593713ddaaabf852ca691f7f220bcd65568fe4fc573e2d309cd +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_O_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_O_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..697459d56fe9046ef54870f14e8a0e1a10aad8fa --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4606564540f6059f62fb8cb9d95a778f813839b4abeeba54857ad5b22750cdb +size 262272 diff --git a/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..df5169d5a96b7a82a286a7e8f19d9995894428e1 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d45b59f9a92b08bd8435b6fbe569424b86ac567b4ccc8c439b09cd16b54de69c +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..886d534eac0898abc977721449c661fea4d3c8ac --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c99279fa0fb7b06dfd4230a5942ef37fda6f84e6149dead0d5eeae85af83bd9 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..77d58f9851305abdb6d0d26b5d0b2e00d4780e27 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9851be788b4bee47517f665fe702f8cd5d75677a9c5a2ebe05d60a26b63f898 +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_O_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_O_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..697459d56fe9046ef54870f14e8a0e1a10aad8fa --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4606564540f6059f62fb8cb9d95a778f813839b4abeeba54857ad5b22750cdb +size 262272 diff --git a/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..f2e39745769b6700aa69a4ee108631c88b3b3f18 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca3c56e27a5e25ace43041942d45be9b8bbbf149dd2967bd5c291afe212a4085 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..124b5192e8f9a774e971e357693d2f3ee89d7889 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f70bf7ddbe123fce2c5045095255f6a89bbb41b0d47b1612cb5e13370b4bc5f +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..4b44948f77e096f6287f81e7bddf812a3094c0a9 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_O_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fcfa41b7cf0dba313cbdb551d90896b27e8ad5baec484033e8ffd8681a341653 +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_S_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_S_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..06ab9840bf9b7f1f4f6842b920ef7e39ffa6f0a7 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88d12a6706e9f755ac19e1ab36e707e88a722330504609f541b605b024d31c4f +size 262272 diff --git a/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..3e31e6b2d020c233993e08f4ab97b085f393cd20 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a25417b3d52fec1bccec3169f8a339056469ab8f8e94dcb549b55375e87a87ba +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..e010a3fe2304345acd1a121a2abff10c15d99917 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7132840e604567edcd68bff56e3a954cfa80951975b35f53a97b362b6d2d428a +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..76bf25eb3930a7be4d7e1352f9a824973141a973 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ab8dc404da835a3b4f1bfba78e422c47b64f8acc1bad7d3447232d35936f1ae +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_S_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_S_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..06ab9840bf9b7f1f4f6842b920ef7e39ffa6f0a7 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88d12a6706e9f755ac19e1ab36e707e88a722330504609f541b605b024d31c4f +size 262272 diff --git a/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..ea585a189eb09e1b6d13191cef1d056b5dc5b507 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f8ce8cb8845cb8ac180dda5926c9bf641bf8ea9c0201a8e308118580ae0a043 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..b3738d23162c1987d173fdaad971210ff071c3a8 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3ed1d25b2305bacc6cce3f5d1c405c8da901e91c4fd092135df7305f3ec9dfa +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..c8362f6ec969fc76b77051df4b006838f6fb9465 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4483c0600eb697fe80af570819c4ab1526fca6e2228e9f673e37bc2998187067 +size 1048704 diff --git a/datasets/Syn-RED/data_3000m_S_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_3000m_S_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..06ab9840bf9b7f1f4f6842b920ef7e39ffa6f0a7 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88d12a6706e9f755ac19e1ab36e707e88a722330504609f541b605b024d31c4f +size 262272 diff --git a/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..4b7fcbed5a1a1430c33362077b81c17e5cf1b121 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14e3ff785ebadb851cc061ce7ff3242baecd065ecb259921cba1a349a1d525f5 +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..fc951952f128f1e51a2ca3276352c230ac47d20c --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:302b30d2709362280e48509050b0955c6055dc19056abafdbbb3f706bc4843be +size 2097280 diff --git a/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..b64b7e8de80e5ea5329eaf7ebe2996ca4d727315 --- /dev/null +++ b/datasets/Syn-RED/data_3000m_S_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ffbcfadda3a7f8bfdf17b1158eac0e4aba0ba3597ed434fbc47e30dd8c5213d +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_Hover_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_Hover_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..780d7219673a41f66000456842ac14b5af3cf6a5 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ae3d1a517a7dacc578d7b0b8848ed813ebe8d01276228cca2be72b96579fb9 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..1ca30f4810db2794882a832c271f717561c1c443 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83dfb9e35e7dc2e9053313c3b0d038bf25528394d38c0c7ff7205e0a33a58e87 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..7dfb5547a91302d732d45ed9113473be4ea7e450 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e3e3299d8cfb20ad3f8d19409f488e287c9ece19d20554f5089668a4de5fc8b +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..b3f008d03006f301240d9999ddfa475342fe30fc --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05b11cccfb4ddc1b2b8b5b8a8866997d6481682959857011c46fa478228d2d80 +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_Hover_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_Hover_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..780d7219673a41f66000456842ac14b5af3cf6a5 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ae3d1a517a7dacc578d7b0b8848ed813ebe8d01276228cca2be72b96579fb9 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..caec7fd4b3151110ae88e60ca18527d93d90d9a4 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:622ace1120600a48c879ac80d00ac18309bb674a026230eacdd58aebc3e2b012 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..b54b229686d061fc8a4c76ea2b672c559cc897a6 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01912f6be372c2d3d6b624a0f177dd5941fffad88d3ff17d00ea079a19fe5f3a +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..5e182a256072d94c4841d028dfec7105ac843813 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:934fc37ba62698df4055a8b63c2ca3e5d9be446adce55475b0e39f1d7405bcfe +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_Hover_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_Hover_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..780d7219673a41f66000456842ac14b5af3cf6a5 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ae3d1a517a7dacc578d7b0b8848ed813ebe8d01276228cca2be72b96579fb9 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..fc47f67c334090471d40cfeca03afe4b851e2cc2 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6679a158d10518b167dc49182249bde86988850c7f3f988db46c1d2f13ec10aa +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..1c898cde33b70de90d6c00605194102be949d3fc --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d3f6496f2ce81530c1481bc13df0db391c811dbbced07e141a3d7808685b2fa2 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..5d4507422cf276aac8d5cf481b8d07e27f2c4bbd --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Hover_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:457fc66c4429552a71980a08608f3b5697c5f6e5be30112b0bbe37193be10ddd +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_Line_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_Line_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..ae5ad25405f5eddf2f7824d79c9c025974ba536d --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:079f8d51b443d84a08eff3fbdc5827c8ea74fbecd0f692f896b44ba3492078a0 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..f767c4e9a99876497020fe74915e69d137ef1700 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ba0e95f393ff467a1f588b9dd5d947223394f38aa219ef42e882a8f7f5edee1 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..1e1eeb4b6e4691b0f43ea9ede90d47c2397ad71c --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8a67ea176303edf5a966e78cf6312bc852079ace9d3e3b6863fc4358c06a052 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..8a90603e54b7c8381b80ee90771f4e5069dbba61 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:429e2ffb9bd30c5d8f6d6aa850f2b4a5cf5128f43ed0ca1492e969d20fcdd225 +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_Line_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_Line_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..ae5ad25405f5eddf2f7824d79c9c025974ba536d --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:079f8d51b443d84a08eff3fbdc5827c8ea74fbecd0f692f896b44ba3492078a0 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..63bf13199c4b2481fbeca930250e3a3b2a63101b --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c1e62335c10a89578726075da0059f19fe76575909acbe17fba6214b39b0533 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..09556ffb3378e92924c023d1abef951db9faeab1 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52aa7619ba0833b7791ffc93a0720898567ac11e6f8de413404bae4fa3c497e1 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..0704c6549b72effe7409e5803c14019e88b6bc83 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:896854137b6a7a6cf53091a4cbc2bf4dcc0f50dfe92e1fc515597f9bad6cdaeb +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_Line_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_Line_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..ae5ad25405f5eddf2f7824d79c9c025974ba536d --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:079f8d51b443d84a08eff3fbdc5827c8ea74fbecd0f692f896b44ba3492078a0 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..20c278e6ed4fed94018341fe9ec89844ab4d6a6a --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dcb85a198a680971ed9c6f132d2835cf9ce7f769ca099ae0262eed0ce7c5b70d +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..9f48eb30583a4313da25bc48df99d1c54e5b7a6e --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a3a7c761bc7de85ce1c0e225785a87e39ceb4f224088e9fe384d62eb324b6a4 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..6ce61435d8c6078075fa2b7716101396b75433d1 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_Line_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec2594dbcfca4bf96b5c97b9cd46079afdb1485cf66dd026fcbe82e199e27999 +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_O_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_O_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..780d7219673a41f66000456842ac14b5af3cf6a5 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ae3d1a517a7dacc578d7b0b8848ed813ebe8d01276228cca2be72b96579fb9 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..8bdb70c1f4ec23fa475f6fca869a6c3a1caa5132 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:255024c81f394a5dd5b8bd2fc5e3f2a0af48c8ed1d9d03f1007ac6470703841d +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..9ff1d7e99e250f22ddf7b587ab8552af5321fc84 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4db046acd2a37a2f2ebc84d026ad6c96a492f176c77da774e0f35ced4dc93ea +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..208f100abc90b788cf1fb4f1d09db4eb5d084847 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9369497dd6ebdad891067cbd4578e518e60deaee8d45a57a49dcb1ebd962fb2 +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_O_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_O_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..780d7219673a41f66000456842ac14b5af3cf6a5 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ae3d1a517a7dacc578d7b0b8848ed813ebe8d01276228cca2be72b96579fb9 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..2b2075d6daa73d22f6096f3ffbc147ae9e501174 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09c0f48aa06867bb90670208c7c3ea0b5e2796bcd20de6d312106c72bbf994cd +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..03a3fa91ffb7e90f3d265711751ff1d09af32353 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5bfa1af4c3332e99f378cec89449ecd31ef0c7db21f416e8582b4fc353fe4ad +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..3095aa1fee71e513679663e961781334615d7ec8 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eba23926a783b90362659cfa56e08b18f67f2fd1ed07a1ae66bf0fc6e9644bf1 +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_O_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_O_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..780d7219673a41f66000456842ac14b5af3cf6a5 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ae3d1a517a7dacc578d7b0b8848ed813ebe8d01276228cca2be72b96579fb9 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..cf5ec83184833e4e91c9aef1840189025a27b418 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:562ba2d7e17d41b597f46318ae1c2956cc87f8df253cf2871d63f6ef61145468 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..5fc830c2ac76d7fc6668dc6feb5827afcbffc326 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdd952d50c88849506e7f27b7ff91a412f8477f25af6020f7ee7802ab358c451 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..85df9efbca628e1a5cca90b264d12a52a5d0d07d --- /dev/null +++ b/datasets/Syn-RED/data_5000m_O_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa3b9c6de9578e5e0d531fbe5084c4b446555a0798213378177c30a6fbc4c289 +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_S_10dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_S_10dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..ae5ad25405f5eddf2f7824d79c9c025974ba536d --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_10dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:079f8d51b443d84a08eff3fbdc5827c8ea74fbecd0f692f896b44ba3492078a0 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..2d95c56c8093cecb320bbf4f8ef38115948fe7e4 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffb48f8d12748d9237f87f18c098c4f3a2eaababa5c9e78238c799d96542443e +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..a6b31ae466a6e908bd808ef6774f4e469952cb67 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4bcfe01088f1a8733786833eaa768e3635dcd3104b3ece9ca9792f3f4cdd49c9 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..943175eadbf4b3324c28952cd7ef4234e0eecbc8 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_10dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc81aaea5023716f3e43bd9aaa8aef18c57cd9f7adf7f9949f9a9c880847cbda +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_S_14dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_S_14dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..ae5ad25405f5eddf2f7824d79c9c025974ba536d --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_14dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:079f8d51b443d84a08eff3fbdc5827c8ea74fbecd0f692f896b44ba3492078a0 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..8774d842cdb8af0f8d8a85b6d58a0af9a33f5c03 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2130e1c5b0b9d1c086e37fc8b753a5e491fd8700ce0025dd8d89f1ea676ca4ac +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..d190d2f5994064f2adb90d1a7d923c0e538b0569 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d0aa673865d71d785e9d31ebf3d855c4d5991f9113272114a0773efdade29e3 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..d86beb867b8eef65cebbdf29dd94d1c9676a9ce9 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_14dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:020fa94563a4fffe9f45734123ae1c6802cf59c96bf8fb418c9a9cf91061e867 +size 1048704 diff --git a/datasets/Syn-RED/data_5000m_S_18dB/annotations/dense/000000/range_doppler.npy b/datasets/Syn-RED/data_5000m_S_18dB/annotations/dense/000000/range_doppler.npy new file mode 100644 index 0000000000000000000000000000000000000000..ae5ad25405f5eddf2f7824d79c9c025974ba536d --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_18dB/annotations/dense/000000/range_doppler.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:079f8d51b443d84a08eff3fbdc5827c8ea74fbecd0f692f896b44ba3492078a0 +size 262272 diff --git a/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_echo/000000.npy b/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_echo/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..3b4787691d9855741e8e82e5137376cbbf3f8359 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_echo/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b6705781c32c2fa8b6f7cf783bf99df496a269f509d1c98194c25ce2119a365 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_mtd/000000.npy b/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_mtd/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..b93701d4dfe3582f81ccfe170c21d7ab7f64a0f5 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_mtd/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51d1adb778ddfcfe6c4d61562214fe2200946bc90e0012a7e251fa8f71c9cbb8 +size 2097280 diff --git a/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_mtdData_amp/000000.npy b/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_mtdData_amp/000000.npy new file mode 100644 index 0000000000000000000000000000000000000000..c2c788ebf8568e86f8c48a2fb555c67d88a15543 --- /dev/null +++ b/datasets/Syn-RED/data_5000m_S_18dB/range_doppler_mtdData_amp/000000.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c648a2372cfd70f35be5ea16c81e19db5e4c4adaf69186655d7e585b1a30ea8 +size 1048704 diff --git a/datasets/Syn-RED/data_seq_ref.json b/datasets/Syn-RED/data_seq_ref.json new file mode 100644 index 0000000000000000000000000000000000000000..decd677dc282ded7d99d6b43ba317ca72e5fb979 --- /dev/null +++ b/datasets/Syn-RED/data_seq_ref.json @@ -0,0 +1 @@ +{"data_1000m_Hover_10dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_Hover_14dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_Hover_18dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_Line_10dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_Line_14dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_Line_18dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_O_10dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_O_14dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_O_18dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_S_10dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_S_14dB": {"split": ["Train", "Validation", "Test"]}, "data_1000m_S_18dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_Hover_10dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_Hover_14dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_Hover_18dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_Line_10dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_Line_14dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_Line_18dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_O_10dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_O_14dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_O_18dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_S_10dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_S_14dB": {"split": ["Train", "Validation", "Test"]}, "data_3000m_S_18dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_Hover_10dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_Hover_14dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_Hover_18dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_Line_10dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_Line_14dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_Line_18dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_O_10dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_O_14dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_O_18dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_S_10dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_S_14dB": {"split": ["Train", "Validation", "Test"]}, "data_5000m_S_18dB": {"split": ["Train", "Validation", "Test"]}} \ No newline at end of file diff --git a/datasets/Syn-RED/dataset_meta.json b/datasets/Syn-RED/dataset_meta.json new file mode 100644 index 0000000000000000000000000000000000000000..164dede7fc065f1ba4775aecc6ea44b381de519b --- /dev/null +++ b/datasets/Syn-RED/dataset_meta.json @@ -0,0 +1,9 @@ +{ + "display_name": "Syn-RED", + "full_name": "Synthetic Radar Echo Dataset", + "scenario": "Low-Slow-Small (LSS) target detection, precise electromagnetic simulation", + "order": 1, + "mtd_fftshift": false, + "mtd_amp_dir": "range_doppler_mtdData_amp", + "valid_classes": [0, 1] +} diff --git a/datasets/Syn-RED/light_dataset_frame_oriented.json b/datasets/Syn-RED/light_dataset_frame_oriented.json new file mode 100644 index 0000000000000000000000000000000000000000..0a2ee82ca96a1da9eb5f93b018a9521fcd3579a0 --- /dev/null +++ b/datasets/Syn-RED/light_dataset_frame_oriented.json @@ -0,0 +1,31 @@ +{ + "data_1000m_Line_10dB": ["000000"], + "data_1000m_Line_14dB": ["000000"], + "data_1000m_Line_18dB": ["000000"], + "data_1000m_O_10dB": ["000000"], + "data_1000m_O_14dB": ["000000"], + "data_1000m_O_18dB": ["000000"], + "data_1000m_S_10dB": ["000000"], + "data_1000m_S_14dB": ["000000"], + "data_1000m_S_18dB": ["000000"], + + "data_3000m_Line_10dB": ["000000"], + "data_3000m_Line_14dB": ["000000"], + "data_3000m_Line_18dB": ["000000"], + "data_3000m_O_10dB": ["000000"], + "data_3000m_O_14dB": ["000000"], + "data_3000m_O_18dB": ["000000"], + "data_3000m_S_10dB": ["000000"], + "data_3000m_S_14dB": ["000000"], + "data_3000m_S_18dB": ["000000"], + + "data_5000m_Line_10dB": ["000000"], + "data_5000m_Line_14dB": ["000000"], + "data_5000m_Line_18dB": ["000000"], + "data_5000m_O_10dB": ["000000"], + "data_5000m_O_14dB": ["000000"], + "data_5000m_O_18dB": ["000000"], + "data_5000m_S_10dB": ["000000"], + "data_5000m_S_14dB": ["000000"], + "data_5000m_S_18dB": ["000000"] +} diff --git a/images/screenshot_echmo_vs_traditional.png b/images/screenshot_echmo_vs_traditional.png new file mode 100644 index 0000000000000000000000000000000000000000..713474b2444fab041df24fc67a4829cc87d6124b --- /dev/null +++ b/images/screenshot_echmo_vs_traditional.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afc5cb4ee13194a99afef7d0dfb3f385778fb323ca5912f616335c2d08c859aa +size 905301 diff --git a/images/screenshot_model_comparison.png b/images/screenshot_model_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..733b7efd67296ae56f79ed6321190e01d02cf7d5 --- /dev/null +++ b/images/screenshot_model_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40b641f42cbbacbab40761f36282ff54876c0a29efbf307b1172c7eab40f4035 +size 561479 diff --git a/logos/logo.jpg b/logos/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..063679cc0bc30e67a9cc66dbdee5b99c0c2d1030 --- /dev/null +++ b/logos/logo.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46daa9d95b7bc6b38b32fb3190ef8790ddc2bbd052ac5163d141cc7c8fd25501 +size 136026 diff --git a/logos/peco-logo-banner-yellow.png b/logos/peco-logo-banner-yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..a5ae632f247b50d37d0d5212894636c644a0923f --- /dev/null +++ b/logos/peco-logo-banner-yellow.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df33e66caeda914c6c720969d9a0bcba1715f0ef36920219bdf309d8fbc272c7 +size 168916 diff --git a/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/config.json b/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/config.json new file mode 100644 index 0000000000000000000000000000000000000000..ea6e3b06e5cd947a9294dfaab31aa01a4aa0f425 --- /dev/null +++ b/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/config.json @@ -0,0 +1,48 @@ +{ + "model": "deeplabv3plus", + "dataset": "HiL-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 9, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 4, + "device": "cuda:0", + "custom_loss": "lsf_wce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 16, + "ReCK_MODE": "deeplabv3plus(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the deeplabv3plus HiL-RED dataset.", + "distributed": false, + "name_exp": "deeplabv3plus_e300_lr0.0001_lsf_wce" +} \ No newline at end of file diff --git a/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/results/deeplabv3plus.pt b/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/results/deeplabv3plus.pt new file mode 100644 index 0000000000000000000000000000000000000000..6832fd718dd7cd892fcd83f6f0fa3c3d2da43825 --- /dev/null +++ b/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/results/deeplabv3plus.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c0c0043045d8fffc87ae4d293e7d20f54c59f612a22857eb62e13a318c8be18 +size 235673268 diff --git a/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/results/deeplabv3plus_results.json b/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/results/deeplabv3plus_results.json new file mode 100644 index 0000000000000000000000000000000000000000..748b0ee2e9d4fcfe5bd4accd2835c6c8836d9162 --- /dev/null +++ b/models/HiL-RED/deeplabv3plus_e300_lr0.0001_lsf_wce_4/results/deeplabv3plus_results.json @@ -0,0 +1,361 @@ +{ + "epoch": 291, + "rd_train_loss": 0.001010617590509355, + "train_loss": 0.001010617590509355, + "val_metrics": { + "range_doppler": { + "loss": 0.35989734530448914, + "loss_ce": 0.7197946906089783, + "loss_dice": 0.0, + "acc": 0.94671171887344, + "acc_by_class": [ + 0.9494698591552032, + 0.9953817409107478, + 0.9999655817656213, + 0.9999846381489665, + 0.9999181351723323, + 0.7728704894756887, + 0.8028150252323997, + 1.0, + 1.0 + ], + "prec": 0.4348148303067785, + "prec_by_class": [ + 0.9999927895271999, + 0.017634464458702457, + 0.6048297734133201, + 0.8228834437844961, + 0.4632009143490458, + 0.4588057690213735, + 0.5459863182068683, + 0.0, + 0.0 + ], + "recall": 0.6496777345063918, + "recall_by_class": [ + 0.9316889596460837, + 0.9327392555462731, + 0.9966628888049364, + 0.9998839691822148, + 0.9314019082108782, + 0.7321387609220259, + 0.32258386824511515, + 0.0, + 0.0 + ], + "miou": 0.49583463311685333, + "miou_by_class": [ + 0.93168270063306, + 0.017612068273493594, + 0.6036073825503355, + 0.8228048733911316, + 0.44792015540223723, + 0.39286049162527353, + 0.2543547599424418 + ], + "dice": 0.6061740927685328, + "dice_by_class": [ + 0.9646332656026334, + 0.034614503183039845, + 0.7528119231046992, + 0.9027898497400328, + 0.6187083597382369, + 0.5641060116051247, + 0.4055547364059631 + ], + "confusion_matrix": [ + [ + 438386954.0, + 24007.0, + 20684.0, + 9264.0, + 46497.0, + 30998459.0, + 1043435.0, + 0.0, + 0.0 + ], + [ + 105.0, + 50242.0, + 0.0, + 0.0, + 0.0, + 2647.0, + 871.0, + 0.0, + 0.0 + ], + [ + 96.0, + 0.0, + 31658.0, + 10.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 5.0, + 0.0, + 0.0, + 43087.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 2955.0, + 0.0, + 0.0, + 0.0, + 40122.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 984276.0, + 0.0, + 0.0, + 0.0, + 114859694.0, + 41038441.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1790555.0, + 0.0, + 0.0, + 0.0, + 104484121.0, + 50607735.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + }, + "global_acc": 0.94671171887344, + "global_prec": 0.4348148303067785, + "global_dice": 0.6061740927685328, + "global_recall": 0.6496777345063918, + "global_miou": 0.49583463311685333, + "miou_by_class": [ + 0.93168270063306, + 0.017612068273493594, + 0.6036073825503355, + 0.8228048733911316, + 0.44792015540223723, + 0.39286049162527353, + 0.2543547599424418 + ] + }, + "test_metrics": { + "range_doppler": { + "loss": 0.3553369641304016, + "loss_ce": 0.7106739282608032, + "loss_dice": 0.0, + "acc": 0.9474549187418826, + "acc_by_class": [ + 0.949482888378173, + 0.9953832530869454, + 0.9999658617912771, + 0.999984706082288, + 0.9999193333761783, + 0.7761005550895381, + 0.8062576708725435, + 1.0, + 1.0 + ], + "prec": 0.43770598374815645, + "prec_by_class": [ + 0.9999925808665839, + 0.017573840951116984, + 0.6059585099939431, + 0.823945536834899, + 0.4659377239418387, + 0.4642291880960963, + 0.5617164730489304, + 0.0, + 0.0 + ], + "recall": 0.6513013727325034, + "recall_by_class": [ + 0.9314246210772342, + 0.9334513143826273, + 0.9986274876785826, + 0.997973097475585, + 0.9287623260528983, + 0.7484450184301727, + 0.3230284894954307, + 0.0, + 0.0 + ], + "miou": 0.4980609554461843, + "miou_by_class": [ + 0.9314181845912264, + 0.017551850334391935, + 0.6054542703684092, + 0.822569009378441, + 0.4498605066398839, + 0.4015722513914207, + 0.2580006154195171 + ], + "dice": 0.6085211269980217, + "dice_by_class": [ + 0.964491467668247, + 0.03449819317623336, + 0.7542466674634082, + 0.9026478565485048, + 0.6205569451049544, + 0.5730311051482316, + 0.4101756538765726 + ], + "confusion_matrix": [ + [ + 220778864.0, + 12268.0, + 10409.0, + 4620.0, + 23103.0, + 15671503.0, + 532761.0, + 0.0, + 0.0 + ], + [ + 47.0, + 25318.0, + 0.0, + 0.0, + 0.0, + 1340.0, + 418.0, + 0.0, + 0.0 + ], + [ + 13.0, + 0.0, + 16007.0, + 9.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 32.0, + 12.0, + 0.0, + 21664.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 1546.0, + 0.0, + 0.0, + 0.0, + 20156.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 494422.0, + 0.0, + 0.0, + 0.0, + 59150359.0, + 19386220.0, + 0.0, + 0.0 + ], + [ + 0.0, + 908644.0, + 0.0, + 0.0, + 0.0, + 52593084.0, + 25529261.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + }, + "global_acc": 0.9474549187418826, + "global_prec": 0.43770598374815645, + "global_dice": 0.6085211269980217, + "global_recall": 0.6513013727325034, + "global_miou": 0.4980609554461843, + "miou_by_class": [ + 0.9314181845912264, + 0.017551850334391935, + 0.6054542703684092, + 0.822569009378441, + 0.4498605066398839, + 0.4015722513914207, + 0.2580006154195171 + ] + } +} \ No newline at end of file diff --git a/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/config.json b/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/config.json new file mode 100644 index 0000000000000000000000000000000000000000..c37603ef881dda053bd81ffd5e0906666593077b --- /dev/null +++ b/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/config.json @@ -0,0 +1,48 @@ +{ + "model": "echmo", + "dataset": "HiL-RED", + "task_name": "Segmentation", + "cmplx_flag": true, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 9, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 0, + "device": "cuda:0", + "custom_loss": "lsf_wce", + "transformations": "hflip,vflip", + "norm_type": "instance", + "shuffle": true, + "num_workers": 1, + "ReCK_MODE": "ReCK-3", + "ReCK_Module": "3 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the EchMo w/ pkcin4any_cuda for HiL-RED dataset(1000_per_class). (w/o BN + no act + [A])", + "distributed": false, + "name_exp": "echmo_e300_lr0.0001_lsf_wce" +} \ No newline at end of file diff --git a/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/results/echmo.pt b/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/results/echmo.pt new file mode 100644 index 0000000000000000000000000000000000000000..b0f55db5299344c707ea683a33afd87ed2976462 --- /dev/null +++ b/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/results/echmo.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2235a47d29c54e8274c355739ddf009e50f3372a6851af61602093df42fd880b +size 5248838 diff --git a/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/results/echmo_results.json b/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/results/echmo_results.json new file mode 100644 index 0000000000000000000000000000000000000000..897848f49678862603786880d5131db83a36b10c --- /dev/null +++ b/models/HiL-RED/echmo_e300_lr0.0001_lsf_wce_0/results/echmo_results.json @@ -0,0 +1 @@ +{"epoch": 211, "rd_train_loss": 4.326968792156549e-06, "train_loss": 4.326968792156549e-06, "val_metrics": {"range_doppler": {"loss": 0.0002015873760683462, "loss_ce": 0.0004031747521366924, "loss_dice": 0.0, "acc": 0.9999994629038823, "acc_by_class": [0.9999978647887319, 0.9999996558160746, 0.9999999222399073, 0.999999975779642, 0.9999980292315442, 0.999999775643044, 0.999999942635996, 1.0, 1.0], "prec": 0.7751589385506339, "prec_by_class": [0.9999983529182861, 0.9965350478978673, 1.0, 0.999559277214632, 0.9803381832481322, 0.9999996430446059, 0.9999999426321823, 0.0, 0.0], "recall": 0.7755976307303958, "recall_by_class": [0.9999980872604533, 0.9984591107398125, 0.9980795869537842, 1.0, 0.9838428859948465, 0.9999992350958962, 0.9999997705287689, 0.0, 0.0], "miou": 0.9939205644148494, "miou_by_class": [0.9999964401850402, 0.995004810182787, 0.9980795869537842, 0.999559277214632, 0.9648052450656771, 0.9999988781410482, 0.9999997131609775], "dice": 0.9969142143931186, "dice_by_class": [0.9999982150893522, 0.9974961464921129, 0.9990388655941718, 0.99977958503747, 0.9820874028880449, 0.9999994340702094, 0.9999998515804683], "confusion_matrix": [[470528400.0, 31.0, 0.0, 19.0, 850.0, 0.0, 0.0, 0.0, 0.0], [18.0, 53782.0, 0.0, 0.0, 0.0, 56.0, 9.0, 0.0, 0.0], [61.0, 0.0, 31703.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 43092.0, 0.0, 0.0, 0.0, 0.0, 0.0], [696.0, 0.0, 0.0, 0.0, 42381.0, 0.0, 0.0, 0.0, 0.0], [0.0, 120.0, 0.0, 0.0, 0.0, 156882291.0, 0.0, 0.0, 0.0], [0.0, 36.0, 0.0, 0.0, 0.0, 0.0, 156882375.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]}, "global_acc": 0.9999994629038823, "global_prec": 0.7751589385506339, "global_dice": 0.9969142143931186, "global_recall": 0.7755976307303958, "global_miou": 0.9939205644148494, "miou_by_class": [0.9999964401850402, 0.995004810182787, 0.9980795869537842, 0.999559277214632, 0.9648052450656771, 0.9999988781410482, 0.9999997131609775]}, "test_metrics": {"range_doppler": {"loss": 0.00033327110577374697, "loss_ce": 0.0006665422115474939, "loss_dice": 0.0, "acc": 0.9999995130230054, "acc_by_class": [0.9999981628715118, 0.9999996027140662, 1.0, 0.9999998911891714, 0.9999983147000566, 0.9999996988724161, 0.999999946859825, 1.0, 1.0], "prec": 0.775371466693309, "prec_by_class": [0.9999985740410897, 0.9958808385435822, 1.0, 0.9996771068776235, 0.9827871109887083, 0.9999996836681617, 0.9999998861206161, 0.0, 0.0], "recall": 0.775918959572357, "recall_by_class": [0.9999983631007677, 0.9983408914943037, 1.0, 0.9983416252072969, 0.9865910975946918, 0.9999988105933265, 0.9999998481608271, 0.0, 0.0], "miou": 0.99458331204412, "miou_by_class": [0.9999969371465257, 0.9942353589131632, 1.0, 0.998019801980198, 0.9698328577252344, 0.9999984942622407, 0.9999997342814777], "dice": 0.9972573208140404, "dice_by_class": [0.9999984635709177, 0.9971093426699946, 0.999999995, 0.9990089147224998, 0.9846854254635948, 0.9999992421305536, 0.9999998621407213], "confusion_matrix": [[237033140.0, 6.0, 0.0, 7.0, 375.0, 0.0, 0.0, 0.0, 0.0], [11.0, 27078.0, 0.0, 0.0, 0.0, 25.0, 9.0, 0.0, 0.0], [0.0, 0.0, 16029.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [36.0, 0.0, 0.0, 21672.0, 0.0, 0.0, 0.0, 0.0, 0.0], [291.0, 0.0, 0.0, 0.0, 21411.0, 0.0, 0.0, 0.0, 0.0], [0.0, 94.0, 0.0, 0.0, 0.0, 79030907.0, 0.0, 0.0, 0.0], [0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 79030977.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]}, "global_acc": 0.9999995130230054, "global_prec": 0.775371466693309, "global_dice": 0.9972573208140404, "global_recall": 0.775918959572357, "global_miou": 0.99458331204412, "miou_by_class": [0.9999969371465257, 0.9942353589131632, 1.0, 0.998019801980198, 0.9698328577252344, 0.9999984942622407, 0.9999997342814777]}} \ No newline at end of file diff --git a/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/config.json b/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/config.json new file mode 100644 index 0000000000000000000000000000000000000000..e0781dc5ffbf3f96d3538cd473b7f17972fd61d4 --- /dev/null +++ b/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/config.json @@ -0,0 +1,48 @@ +{ + "model": "fcn8s", + "dataset": "HiL-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 9, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 2, + "device": "cuda:0", + "custom_loss": "lsf_wce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 16, + "ReCK_MODE": "fcn8s(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the fcn8s HiL-RED dataset.", + "distributed": false, + "name_exp": "fcn8s_e300_lr0.0001_lsf_wce" +} \ No newline at end of file diff --git a/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/results/fcn8s.pt b/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/results/fcn8s.pt new file mode 100644 index 0000000000000000000000000000000000000000..6af2c63811f485556003cee054555658fefc5058 --- /dev/null +++ b/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/results/fcn8s.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f610c65e320bdf4f9ccbb8d9283481a54d4eb7d90675d4e4f917779e0ce966d6 +size 537321442 diff --git a/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/results/fcn8s_results.json b/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/results/fcn8s_results.json new file mode 100644 index 0000000000000000000000000000000000000000..5dae4b7595dc9544681b789a8189182bd0e6eae0 --- /dev/null +++ b/models/HiL-RED/fcn8s_e300_lr0.0001_lsf_wce_2/results/fcn8s_results.json @@ -0,0 +1,361 @@ +{ + "epoch": 291, + "rd_train_loss": 0.0005426889401860535, + "train_loss": 0.0005426889401860535, + "val_metrics": { + "range_doppler": { + "loss": 0.0016010735416784883, + "loss_ce": 0.0032021470833569765, + "loss_dice": 0.0, + "acc": 0.9999829819002516, + "acc_by_class": [ + 0.9999715130075647, + 0.9999444017719836, + 0.9999926263204529, + 0.9999983286740991, + 0.9999880713683872, + 0.9999748172421007, + 0.9999770787176764, + 1.0, + 1.0 + ], + "prec": 0.6899218008861006, + "prec_by_class": [ + 0.9999994516558898, + 0.568055979711338, + 0.8470663674254568, + 0.9704749679075738, + 0.8237700195875101, + 0.9999727037249235, + 0.9999567179622133, + 0.0, + 0.0 + ], + "recall": 0.7542178316425984, + "recall_by_class": [ + 0.9999530571209911, + 0.7942448714378539, + 0.9981110691348697, + 1.0, + 0.99582143603315, + 0.9999013783642068, + 0.9999286726923134, + 0.0, + 0.0 + ], + "miou": 0.8760021313598143, + "miou_by_class": [ + 0.9999525088283614, + 0.4951849622667716, + 0.8457106274007683, + 0.9704749679075738, + 0.8209323688138707, + 0.9998740874727979, + 0.9998853968285555 + ], + "dice": 0.9236161687103122, + "dice_by_class": [ + 0.9999762488503144, + 0.6623728450039136, + 0.9164065160185896, + 0.9850162816460737, + 0.9016615645500159, + 0.9999370347726584, + 0.9999426901306179 + ], + "confusion_matrix": [ + [ + 470507212.0, + 5869.0, + 5724.0, + 1311.0, + 9177.0, + 3.0, + 4.0, + 0.0, + 0.0 + ], + [ + 18.0, + 42782.0, + 0.0, + 0.0, + 0.0, + 4279.0, + 6786.0, + 0.0, + 0.0 + ], + [ + 60.0, + 0.0, + 31704.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 43092.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 180.0, + 0.0, + 0.0, + 0.0, + 42897.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 15472.0, + 0.0, + 0.0, + 0.0, + 156866939.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 11190.0, + 0.0, + 0.0, + 0.0, + 0.0, + 156871221.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + }, + "global_acc": 0.9999829819002516, + "global_prec": 0.6899218008861006, + "global_dice": 0.9236161687103122, + "global_recall": 0.7542178316425984, + "global_miou": 0.8760021313598143, + "miou_by_class": [ + 0.9999525088283614, + 0.4951849622667716, + 0.8457106274007683, + 0.9704749679075738, + 0.8209323688138707, + 0.9998740874727979, + 0.9998853968285555 + ] + }, + "test_metrics": { + "range_doppler": { + "loss": 0.001424356596544385, + "loss_ce": 0.00284871319308877, + "loss_dice": 0.0, + "acc": 0.9999816436011008, + "acc_by_class": [ + 0.9999661734357818, + 0.9999437611495533, + 0.9999926534662742, + 0.9999983044418148, + 0.9999826144746752, + 0.9999746178421315, + 0.9999766675996759, + 1.0, + 1.0 + ], + "prec": 0.6825841632015802, + "prec_by_class": [ + 0.9999995991905354, + 0.5641280728853051, + 0.846661736742024, + 0.971577154128934, + 0.7609613625167148, + 0.9999727935131029, + 0.9999567498376063, + 0.0, + 0.0 + ], + "recall": 0.7543354824196125, + "recall_by_class": [ + 0.9999440079211073, + 0.794454890683184, + 1.0, + 0.9983416252072969, + 0.996451939913372, + 0.9999002922916287, + 0.9999265857599227, + 0.0, + 0.0 + ], + "miou": 0.8667938077297637, + "miou_by_class": [ + 0.9999436071565256, + 0.4922781686923147, + 0.846661736742024, + 0.9700116372750873, + 0.7589050710650992, + 0.9998730912297803, + 0.999883341947514 + ], + "dice": 0.9177554908030149, + "dice_by_class": [ + 0.9999717977832022, + 0.659767294592577, + 0.916964612751359, + 0.9847775657738589, + 0.8629289655606477, + 0.9999365365881757, + 0.9999416625712834 + ], + "confusion_matrix": [ + [ + 237020256.0, + 2967.0, + 2903.0, + 634.0, + 6766.0, + 1.0, + 1.0, + 0.0, + 0.0 + ], + [ + 3.0, + 21548.0, + 0.0, + 0.0, + 6.0, + 2149.0, + 3417.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 16029.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 15.0, + 0.0, + 0.0, + 21672.0, + 21.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 77.0, + 0.0, + 0.0, + 0.0, + 21625.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 7880.0, + 0.0, + 0.0, + 0.0, + 79023121.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 5802.0, + 0.0, + 0.0, + 0.0, + 0.0, + 79025187.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + }, + "global_acc": 0.9999816436011008, + "global_prec": 0.6825841632015802, + "global_dice": 0.9177554908030149, + "global_recall": 0.7543354824196125, + "global_miou": 0.8667938077297637, + "miou_by_class": [ + 0.9999436071565256, + 0.4922781686923147, + 0.846661736742024, + 0.9700116372750873, + 0.7589050710650992, + 0.9998730912297803, + 0.999883341947514 + ] + } +} \ No newline at end of file diff --git a/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/config.json b/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/config.json new file mode 100644 index 0000000000000000000000000000000000000000..396d5e28e8744413d6680b521331727432251038 --- /dev/null +++ b/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/config.json @@ -0,0 +1,48 @@ +{ + "model": "tmva_net_sv", + "dataset": "HiL-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 9, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 0, + "device": "cuda:0", + "custom_loss": "lsf_wce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 1, + "ReCK_MODE": "tmva_net_sv(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the tmva_net HiL-RED dataset.", + "distributed": false, + "name_exp": "tmva_net_sv_e300_lr0.0001_lsf_wce" +} \ No newline at end of file diff --git a/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/results/tmva_net_sv.pt b/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/results/tmva_net_sv.pt new file mode 100644 index 0000000000000000000000000000000000000000..5c2b198630786e815a0d4d7537b2d645b6be95ed --- /dev/null +++ b/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/results/tmva_net_sv.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:700b82615d5671fc3d4680b5b1c42a16f5a27a133dad439e480ac07ed732c594 +size 4668618 diff --git a/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/results/tmva_net_sv_results.json b/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/results/tmva_net_sv_results.json new file mode 100644 index 0000000000000000000000000000000000000000..a6cfe6c696c04480eba60b90c2e05386dc8c77c2 --- /dev/null +++ b/models/HiL-RED/tmva_net_sv_e300_lr0.0001_lsf_wce_0/results/tmva_net_sv_results.json @@ -0,0 +1 @@ +{"epoch": 163, "rd_train_loss": 0.0005444159614853561, "train_loss": 0.0005444159614853561, "val_metrics": {"range_doppler": {"loss": 264.37518310546875, "loss_ce": 528.7503662109375, "loss_dice": 0.0, "acc": 0.9393204914314014, "acc_by_class": [0.8681036487845227, 0.9998705411789797, 0.999959169813757, 0.9999813596816801, 0.9999577705164368, 0.7890033929612489, 0.7970085399459871, 1.0, 1.0], "prec": 0.48525613233505854, "prec_by_class": [0.8408521097078863, 0.3725440428256631, 0.5718941611887532, 0.7977407407407408, 0.7297100539726371, 0.4999775665517427, 0.5545865160281046, 0.0, 0.0], "recall": 0.5546266369404917, "recall_by_class": [0.9997900768347476, 0.5994801819363222, 0.9778050623347185, 0.9996751137102015, 0.674791652157764, 0.4984982032179503, 0.24159944227272234, 0.0, 0.0], "miou": 0.5108499389126827, "miou_by_class": [0.8407036822969622, 0.29829747531200634, 0.5645653833569637, 0.7975339726737513, 0.5398558799494837, 0.33265526852122423, 0.2023379102783873], "dice": 0.6455746174412285, "dice_by_class": [0.9134590057215773, 0.45952099255448686, 0.7216897238293185, 0.8873645565099846, 0.7011771466865333, 0.49923678395647364, 0.33657411283022504], "confusion_matrix": [[470430525.0, 54386.0, 23215.0, 10421.0, 10733.0, 20.0, 0.0, 0.0, 0.0], [14522.0, 32291.0, 7.0, 0.0, 0.0, 6074.0, 971.0, 0.0, 0.0], [303.0, 0.0, 31059.0, 368.0, 34.0, 0.0, 0.0, 0.0, 0.0], [11.0, 0.0, 3.0, 43078.0, 0.0, 0.0, 0.0, 0.0, 0.0], [13851.0, 0.0, 25.0, 133.0, 29068.0, 0.0, 0.0, 0.0, 0.0], [48236409.0, 0.0, 0.0, 0.0, 0.0, 78205600.0, 30440402.0, 0.0, 0.0], [40773184.0, 0.0, 0.0, 0.0, 0.0, 78206524.0, 37902703.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]}, "global_acc": 0.9393204914314014, "global_prec": 0.48525613233505854, "global_dice": 0.6455746174412285, "global_recall": 0.5546266369404917, "global_miou": 0.5108499389126827, "miou_by_class": [0.8407036822969622, 0.29829747531200634, 0.5645653833569637, 0.7975339726737513, 0.5398558799494837, 0.33265526852122423, 0.2023379102783873]}, "test_metrics": {"range_doppler": {"loss": 264.3960266113281, "loss_ce": 528.7920532226562, "loss_dice": 0.0, "acc": 0.939312860458071, "acc_by_class": [0.8680910791032191, 0.9998705312455501, 0.9999589535538974, 0.9999803374825632, 0.9999584866365441, 0.7889987916561081, 0.7969575644447565, 1.0, 1.0], "prec": 0.48517309620864574, "prec_by_class": [0.8408427776579347, 0.37242421467167325, 0.5710121693507251, 0.789636701526801, 0.73836357204225, 0.49998344552285784, 0.5542949851055697, 0.0, 0.0], "recall": 0.5542935555950909, "recall_by_class": [0.9997898356387793, 0.599712421192346, 0.9777278682388172, 0.9982494932743688, 0.6732098424108377, 0.4985247877601854, 0.24142775184048373, 0.0, 0.0], "miou": 0.5099418139899955, "miou_by_class": [0.8406941830003429, 0.2982781068343939, 0.5636801783980147, 0.7885448127797388, 0.543547006957104, 0.33266970931624923, 0.20217870064412488], "dice": 0.6450828416453307, "dice_by_class": [0.9134533983940628, 0.45949801078201225, 0.7209660678002562, 0.8817724920671164, 0.7042830579912014, 0.4992530462109241, 0.33635381827174204], "confusion_matrix": [[236983712.0, 27410.0, 11764.0, 5465.0, 5167.0, 10.0, 0.0, 0.0, 0.0], [7180.0, 16266.0, 4.0, 0.0, 0.0, 3133.0, 540.0, 0.0, 0.0], [88.0, 0.0, 15672.0, 259.0, 10.0, 0.0, 0.0, 0.0, 0.0], [37.0, 0.0, 1.0, 21670.0, 0.0, 0.0, 0.0, 0.0, 0.0], [7038.0, 0.0, 5.0, 49.0, 14610.0, 0.0, 0.0, 0.0, 0.0], [24290303.0, 0.0, 0.0, 0.0, 0.0, 39398913.0, 15341785.0, 0.0, 0.0], [20552336.0, 0.0, 0.0, 0.0, 0.0, 39398379.0, 19080274.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]}, "global_acc": 0.939312860458071, "global_prec": 0.48517309620864574, "global_dice": 0.6450828416453307, "global_recall": 0.5542935555950909, "global_miou": 0.5099418139899955, "miou_by_class": [0.8406941830003429, 0.2982781068343939, 0.5636801783980147, 0.7885448127797388, 0.543547006957104, 0.33266970931624923, 0.20217870064412488]}} \ No newline at end of file diff --git a/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/config.json b/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/config.json new file mode 100644 index 0000000000000000000000000000000000000000..86b159ebbdf2fefe9d7f1008d9e41bdb072c1939 --- /dev/null +++ b/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/config.json @@ -0,0 +1,48 @@ +{ + "model": "unet", + "dataset": "HiL-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 9, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 0, + "device": "cuda:0", + "custom_loss": "lsf_wce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 1, + "ReCK_MODE": "unet(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the fcn8s HiL-RED dataset.", + "distributed": false, + "name_exp": "unet_e300_lr0.0001_lsf_wce" +} \ No newline at end of file diff --git a/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/results/unet.pt b/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/results/unet.pt new file mode 100644 index 0000000000000000000000000000000000000000..53caa67e30dcb2ac7dab45144c2b34976f55db19 --- /dev/null +++ b/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/results/unet.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9191c9ec10e55e330c4ae7d6de7c63adb4505f67fa9ec3d856c7a9cf3fd6eda +size 69136274 diff --git a/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/results/unet_results.json b/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/results/unet_results.json new file mode 100644 index 0000000000000000000000000000000000000000..3a13db6e47509bc2f29e873836d6b595e63bf9e0 --- /dev/null +++ b/models/HiL-RED/unet_e300_lr0.0001_lsf_wce_0/results/unet_results.json @@ -0,0 +1,361 @@ +{ + "epoch": 291, + "rd_train_loss": 0.0011868419824168086, + "train_loss": 0.0011868419824168086, + "val_metrics": { + "range_doppler": { + "loss": 1.0899347066879272, + "loss_ce": 2.1798694133758545, + "loss_dice": 0.0, + "acc": 0.9267550952435515, + "acc_by_class": [ + 0.9997783292066574, + 0.9998466483748679, + 0.9999812939773673, + 0.9999955591572935, + 0.9998438603915286, + 0.6706887095483487, + 0.6706614565359001, + 1.0, + 1.0 + ], + "prec": 0.4124351596849713, + "prec_by_class": [ + 0.9999759265524536, + 0.38133087857813025, + 0.7825112107623319, + 0.9490920310296191, + 0.3156618320106444, + 0.029591505407935797, + 0.25375305282362653, + 0.0, + 0.0 + ], + "recall": 0.5427633042322338, + "recall_by_class": [ + 0.9997761988467031, + 0.7998143506915437, + 0.9558934642992066, + 0.9993966397475169, + 0.7765396847505629, + 0.02032900934955672, + 0.3331203904050149, + 0.0, + 0.0 + ], + "miou": 0.5030706836068302, + "miou_by_class": [ + 0.9997521361731518, + 0.34810643094351207, + 0.7552421461084994, + 0.9485485220915378, + 0.2893760218690796, + 0.012197461729013561, + 0.16827206633301672 + ], + "dice": 0.5873568198854991, + "dice_by_class": [ + 0.9998760477255532, + 0.5164376046373214, + 0.8605560702134133, + 0.973594967196668, + 0.44886210742483873, + 0.024100948178237918, + 0.288069993822462 + ], + "confusion_matrix": [ + [ + 470423995.0, + 22054.0, + 8414.0, + 2309.0, + 72485.0, + 40.0, + 3.0, + 0.0, + 0.0 + ], + [ + 287.0, + 43082.0, + 25.0, + 1.0, + 0.0, + 3280.0, + 7190.0, + 0.0, + 0.0 + ], + [ + 1366.0, + 0.0, + 30363.0, + 0.0, + 35.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 26.0, + 0.0, + 0.0, + 43066.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 9626.0, + 0.0, + 0.0, + 0.0, + 33451.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 19.0, + 9913.0, + 0.0, + 0.0, + 0.0, + 3189264.0, + 153683215.0, + 0.0, + 0.0 + ], + [ + 1.0, + 37929.0, + 0.0, + 0.0, + 0.0, + 104583751.0, + 52260730.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + }, + "global_acc": 0.9267550952435515, + "global_prec": 0.4124351596849713, + "global_dice": 0.5873568198854991, + "global_recall": 0.5427633042322338, + "global_miou": 0.5030706836068302, + "miou_by_class": [ + 0.9997521361731518, + 0.34810643094351207, + 0.7552421461084994, + 0.9485485220915378, + 0.2893760218690796, + 0.012197461729013561, + 0.16827206633301672 + ] + }, + "test_metrics": { + "range_doppler": { + "loss": 1.0894134044647217, + "loss_ce": 2.1788268089294434, + "loss_dice": 0.0, + "acc": 0.926798449444905, + "acc_by_class": [ + 0.9997811592442171, + 0.9998435353172437, + 0.9999814917635557, + 0.9999954313520639, + 0.9998469107862187, + 0.6708832229656224, + 0.6708542935752241, + 1.0, + 1.0 + ], + "prec": 0.41262352161062676, + "prec_by_class": [ + 0.9999767877082961, + 0.3754186841602888, + 0.7823526425343961, + 0.9490819858901889, + 0.32188201558284757, + 0.03096507392549024, + 0.2539345046941331, + 0.0, + 0.0 + ], + "recall": 0.5441179987612117, + "recall_by_class": [ + 0.9997784321887155, + 0.7975518932271504, + 0.9613824942292095, + 0.9977427676432652, + 0.7861948207538476, + 0.02130280495877814, + 0.3331087758499391, + 0.0, + 0.0 + ], + "miou": 0.5035970484727369, + "miou_by_class": [ + 0.9997552301819461, + 0.34275573583470653, + 0.7585154557983855, + 0.9470485351989506, + 0.29597377140180753, + 0.012781737607890907, + 0.16834887328547196 + ], + "dice": 0.5880095646768589, + "dice_by_class": [ + 0.9998775951110739, + 0.510525814584616, + 0.862677036982953, + 0.9728042349366501, + 0.4567588870422978, + 0.025240848423377007, + 0.28818253565704577 + ], + "confusion_matrix": [ + [ + 236981009.0, + 11123.0, + 4258.0, + 1161.0, + 35944.0, + 24.0, + 9.0, + 0.0, + 0.0 + ], + [ + 176.0, + 21632.0, + 29.0, + 1.0, + 1.0, + 1680.0, + 3604.0, + 0.0, + 0.0 + ], + [ + 619.0, + 0.0, + 15410.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 49.0, + 0.0, + 0.0, + 21659.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 4640.0, + 0.0, + 0.0, + 0.0, + 17062.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 16.0, + 4861.0, + 0.0, + 0.0, + 0.0, + 1683582.0, + 77342542.0, + 0.0, + 0.0 + ], + [ + 1.0, + 20005.0, + 0.0, + 0.0, + 0.0, + 52685067.0, + 26325916.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + }, + "global_acc": 0.926798449444905, + "global_prec": 0.41262352161062676, + "global_dice": 0.5880095646768589, + "global_recall": 0.5441179987612117, + "global_miou": 0.5035970484727369, + "miou_by_class": [ + 0.9997552301819461, + 0.34275573583470653, + 0.7585154557983855, + 0.9470485351989506, + 0.29597377140180753, + 0.012781737607890907, + 0.16834887328547196 + ] + } +} \ No newline at end of file diff --git a/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/config.json b/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/config.json new file mode 100644 index 0000000000000000000000000000000000000000..a4643e2a33d124114504372ad4c77b182ba23564 --- /dev/null +++ b/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/config.json @@ -0,0 +1,48 @@ +{ + "model": "vit", + "dataset": "HiL-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 9, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 0, + "device": "cuda:0", + "custom_loss": "lsf_wce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 1, + "ReCK_MODE": "vit(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the vit HiL-RED dataset.", + "distributed": false, + "name_exp": "vit_e300_lr0.0001_lsf_wce" +} \ No newline at end of file diff --git a/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/results/vit.pt b/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/results/vit.pt new file mode 100644 index 0000000000000000000000000000000000000000..7349206b03d6d1dbee88b5229d72b669ad8b5adc --- /dev/null +++ b/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/results/vit.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e79c0a95e7a4adbbfb13f7e2b5aae05c30d30488690bc4fd2ce0b1c616d5204 +size 5573654 diff --git a/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/results/vit_results.json b/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/results/vit_results.json new file mode 100644 index 0000000000000000000000000000000000000000..f2494b954f9d577721771e525563ee4e36515d09 --- /dev/null +++ b/models/HiL-RED/vit_e300_lr0.0001_lsf_wce_0/results/vit_results.json @@ -0,0 +1,361 @@ +{ + "epoch": 291, + "rd_train_loss": 0.10904882103204727, + "train_loss": 0.10904882103204727, + "val_metrics": { + "range_doppler": { + "loss": 0.24455322325229645, + "loss_ce": 0.4891064465045929, + "loss_dice": 0.0, + "acc": 0.9676872242299004, + "acc_by_class": [ + 0.9987157732338714, + 0.9997889635857649, + 0.9998534932568242, + 0.9999468609441244, + 0.999049126960209, + 0.8559156130459792, + 0.8559151870423295, + 1.0, + 1.0 + ], + "prec": 0.37394033423045875, + "prec_by_class": [ + 0.9999946345526988, + 0.22933152274550953, + 0.24319064645419372, + 0.5473952038674385, + 0.060558992455225974, + 0.6606638193918932, + 0.6243281886071689, + 0.0, + 0.0 + ], + "recall": 0.6566994060490887, + "recall_by_class": [ + 0.9981725091296121, + 0.6897614406386336, + 0.991405364563657, + 0.9985148055323494, + 0.9521554425795669, + 0.5764005437167842, + 0.7038845482811964, + 0.0, + 0.0 + ], + "miou": 0.42789337509155795, + "miou_by_class": [ + 0.9981671632749514, + 0.2078882727827172, + 0.2426790172929318, + 0.5469498786052956, + 0.0603752699267389, + 0.44473425201231226, + 0.4944597717459587 + ], + "dice": 0.5474670103614746, + "dice_by_class": [ + 0.9990827360445298, + 0.34421771484195596, + 0.3905739325283398, + 0.7071332854822315, + 0.11387528744373213, + 0.6156623583856784, + 0.661723757803855 + ], + "confusion_matrix": [ + [ + 469669412.0, + 90069.0, + 97975.0, + 35577.0, + 636267.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 130.0, + 37154.0, + 17.0, + 0.0, + 7.0, + 5472.0, + 11085.0, + 0.0, + 0.0 + ], + [ + 273.0, + 0.0, + 31491.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 56.0, + 0.0, + 8.0, + 43028.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 2061.0, + 0.0, + 0.0, + 0.0, + 41016.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 20005.0, + 0.0, + 0.0, + 0.0, + 90427107.0, + 66435299.0, + 0.0, + 0.0 + ], + [ + 0.0, + 14782.0, + 0.0, + 0.0, + 0.0, + 46440524.0, + 110427105.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + }, + "global_acc": 0.9676872242299004, + "global_prec": 0.37394033423045875, + "global_dice": 0.5474670103614746, + "global_recall": 0.6566994060490887, + "global_miou": 0.42789337509155795, + "miou_by_class": [ + 0.9981671632749514, + 0.2078882727827172, + 0.2426790172929318, + 0.5469498786052956, + 0.0603752699267389, + 0.44473425201231226, + 0.4944597717459587 + ] + }, + "test_metrics": { + "range_doppler": { + "loss": 0.2326589673757553, + "loss_ce": 0.4653179347515106, + "loss_dice": 0.0, + "acc": 0.9691918057753688, + "acc_by_class": [ + 0.9987130464761704, + 0.9997927978739458, + 0.9998532147614437, + 0.9999473259432808, + 0.9990444145842339, + 0.8626890844642888, + 0.8626863678749559, + 1.0, + 1.0 + ], + "prec": 0.37759231174634955, + "prec_by_class": [ + 0.9999951647739785, + 0.23058607604355266, + 0.2420126703431931, + 0.5476756538014063, + 0.06009874170882193, + 0.6762937029840369, + 0.6416687960621567, + 0.0, + 0.0 + ], + "recall": 0.6606746928660142, + "recall_by_class": [ + 0.9981535692284005, + 0.6855436345536998, + 0.9938236945536215, + 0.9975124378109452, + 0.9569164132338034, + 0.6026324657079821, + 0.7114900207056754, + 0.0, + 0.0 + ], + "miou": 0.4331562744422194, + "miou_by_class": [ + 0.9981487518416715, + 0.20853006156986328, + 0.2416492218075908, + 0.5469286724590826, + 0.059936562544194084, + 0.46771947194515284, + 0.5091811789279808 + ], + "dice": 0.5522485232893105, + "dice_by_class": [ + 0.9990735133471133, + 0.3450970164908914, + 0.3892391113497395, + 0.7071155621546459, + 0.11309462107994238, + 0.6373417771287899, + 0.6747780614740512 + ], + "confusion_matrix": [ + [ + 236595862.0, + 45136.0, + 49874.0, + 17884.0, + 324772.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 65.0, + 18594.0, + 19.0, + 0.0, + 0.0, + 2972.0, + 5473.0, + 0.0, + 0.0 + ], + [ + 90.0, + 0.0, + 15930.0, + 0.0, + 9.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 54.0, + 0.0, + 0.0, + 21654.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 935.0, + 0.0, + 0.0, + 0.0, + 20767.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 9083.0, + 0.0, + 0.0, + 0.0, + 47626647.0, + 31395271.0, + 0.0, + 0.0 + ], + [ + 0.0, + 7825.0, + 0.0, + 0.0, + 0.0, + 22793404.0, + 56229760.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + }, + "global_acc": 0.9691918057753688, + "global_prec": 0.37759231174634955, + "global_dice": 0.5522485232893105, + "global_recall": 0.6606746928660142, + "global_miou": 0.4331562744422194, + "miou_by_class": [ + 0.9981487518416715, + 0.20853006156986328, + 0.2416492218075908, + 0.5469286724590826, + 0.059936562544194084, + 0.46771947194515284, + 0.5091811789279808 + ] + } +} \ No newline at end of file diff --git a/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/config.json b/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/config.json new file mode 100644 index 0000000000000000000000000000000000000000..ec842948ca02caf10ca034d520bf772ba1a280f7 --- /dev/null +++ b/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/config.json @@ -0,0 +1,48 @@ +{ + "model": "deeplabv3plus", + "dataset": "Syn-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 2, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 1, + "device": "cuda:0", + "custom_loss": "ce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 16, + "ReCK_MODE": "deeplabv3plus(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the deeplabv3plus Syn-RED dataset.", + "distributed": false, + "name_exp": "deeplabv3plus_e300_lr0.0001_ce" +} \ No newline at end of file diff --git a/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/results/deeplabv3plus.pt b/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/results/deeplabv3plus.pt new file mode 100644 index 0000000000000000000000000000000000000000..21d5244f38d068b0b6c05baccc529e4c73458696 --- /dev/null +++ b/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/results/deeplabv3plus.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:697a3f91e74a7990607f893510e6066a5a04ae89d41933d757c0440fd2f41382 +size 235668386 diff --git a/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/results/deeplabv3plus_results.json b/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/results/deeplabv3plus_results.json new file mode 100644 index 0000000000000000000000000000000000000000..14bdc9ba6383abe2b4aa916a0cd479289bb9c5c9 --- /dev/null +++ b/models/Syn-RED/deeplabv3plus_e300_lr0.0001_ce_1/results/deeplabv3plus_results.json @@ -0,0 +1 @@ +{"epoch": 172, "rd_train_loss": 1.8260459455632372e-06, "train_loss": 1.8260459455632372e-06, "val_metrics": {"range_doppler": {"loss": 0.0004435681039467454, "loss_ce": 0.0008871362078934908, "loss_dice": 0.0, "acc": 0.9999813020906034, "acc_by_class": [0.9999813020906034, 0.9999813020906034], "prec": 0.9883147382911308, "prec_by_class": [0.9999852797035901, 0.9766441968786714], "recall": 0.9593748467332949, "recall_by_class": [0.9999960191573599, 0.9187536743092298], "miou": 0.9494913321195788, "miou_by_class": [0.9999812989781474, 0.8990013652610103], "dice": 0.9734027546353787, "dice_by_class": [0.9999906444016409, 0.9468148648691165], "confusion_matrix": [[704119478.0, 2803.0], [10365.0, 117210.0]]}, "global_acc": 0.9999813020906034, "global_prec": 0.9883147382911308, "global_dice": 0.9734027546353787, "global_recall": 0.9593748467332949, "global_miou": 0.9494913321195788, "miou_by_class": [0.9999812989781474, 0.8990013652610103]}, "test_metrics": {"range_doppler": {"loss": 0.00019492038700263947, "loss_ce": 0.00038984077400527894, "loss_dice": 0.0, "acc": 0.9999931875410034, "acc_by_class": [0.9999931875410034, 0.9999931875410034], "prec": 0.9935534905767589, "prec_by_class": [0.9999955899639847, 0.9871113911895331], "recall": 0.9883013291387464, "recall_by_class": [0.9999975963016894, 0.9766050619758034], "miou": 0.9821509669708295, "miou_by_class": [0.9999931862868748, 0.9643087476547842], "dice": 0.9909133520451943, "dice_by_class": [0.9999965881318308, 0.9818301159585576], "confusion_matrix": [[357365120.0, 859.0], [1576.0, 65789.0]]}, "global_acc": 0.9999931875410034, "global_prec": 0.9935534905767589, "global_dice": 0.9909133520451943, "global_recall": 0.9883013291387464, "global_miou": 0.9821509669708295, "miou_by_class": [0.9999931862868748, 0.9643087476547842]}} \ No newline at end of file diff --git a/models/Syn-RED/echmo_e300_lr0.0001_ce_3/config.json b/models/Syn-RED/echmo_e300_lr0.0001_ce_3/config.json new file mode 100644 index 0000000000000000000000000000000000000000..df04fb3973825154ee0e57dc9d182f52f35097e1 --- /dev/null +++ b/models/Syn-RED/echmo_e300_lr0.0001_ce_3/config.json @@ -0,0 +1 @@ +{"model": "echmo", "dataset": "Syn-RED", "task_name": "Segmentation", "cmplx_flag": true, "process_signal": true, "annot_format": "light_frame", "annot_type": "dense", "w_size": 128, "h_size": 1024, "nb_classes": 2, "nb_input_channels": 1, "lmf_chains": 1, "lmf_channels": 1, "lmf_layers": 1, "lmf_coefs": "tay_mf", "ldc_channels": 1, "ldc_orders": 3, "nb_doppler": 128, "activation": "None", "bias": false, "nb_epochs": 300, "batch_size": 8, "lr": 0.0001, "lr_step": 20, "schedular": "cos", "Tmax": 300, "loss_step": 100, "val_step": 2000, "viz_step": 4000, "torch_seed": 42, "numpy_seed": 42, "version": 3, "device": "cuda:0", "custom_loss": "ce", "transformations": "hflip,vflip", "norm_type": "instance", "shuffle": true, "num_workers": 1, "ReCK_MODE": "echmo_debug_LMF_ReCK0(adamw)", "ReCK_Module": "LMFChains", "scale_factor": 0.1, "num_heads": 1, "pin_mem": true, "comments": "This is a test to train the EchMo w/ pkcin4any_cuda for Syn-RED dataset. (w/o BN + no act + [A])", "distributed": false, "name_exp": "echmo_e300_lr0.0001_ce"} \ No newline at end of file diff --git a/models/Syn-RED/echmo_e300_lr0.0001_ce_3/results/echmo.pt b/models/Syn-RED/echmo_e300_lr0.0001_ce_3/results/echmo.pt new file mode 100644 index 0000000000000000000000000000000000000000..f3251e84fb5bb714b5152473c5bce08bf7de7ff7 --- /dev/null +++ b/models/Syn-RED/echmo_e300_lr0.0001_ce_3/results/echmo.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c4f2c4a4a43e593ddc275bf56e6213de2a0e842d9d77a0bb30a0bfa67247ab7 +size 5639030 diff --git a/models/Syn-RED/echmo_e300_lr0.0001_ce_3/results/echmo_results.json b/models/Syn-RED/echmo_e300_lr0.0001_ce_3/results/echmo_results.json new file mode 100644 index 0000000000000000000000000000000000000000..1061ea421633b3a6b200113df1308901039f3c3b --- /dev/null +++ b/models/Syn-RED/echmo_e300_lr0.0001_ce_3/results/echmo_results.json @@ -0,0 +1 @@ +{"epoch": 20, "rd_train_loss": 0.00035166763700544834, "train_loss": 0.00035166763700544834, "val_metrics": {"range_doppler": {"loss": 0.00027512761880643666, "loss_ce": 0.0005502552376128733, "loss_dice": 0.0, "acc": 0.9999599772726117, "acc_by_class": [0.9999599772726117, 0.9999599772726117], "prec": 0.9294935738194514, "prec_by_class": [0.999987689448547, 0.8589994581903558], "recall": 0.9660139669600324, "recall_by_class": [0.9999722803829297, 0.932055653537135], "miou": 0.9041698515320529, "miou_by_class": [0.9999599705139505, 0.8083797325501554], "dice": 0.9470087844248294, "dice_by_class": [0.9999799798563774, 0.8940375889932815], "confusion_matrix": [[704102763.0, 19518.0], [8668.0, 118907.0]]}, "global_acc": 0.9999599772726117, "global_prec": 0.9294935738194514, "global_dice": 0.9470087844248294, "global_recall": 0.9660139669600324, "global_miou": 0.9041698515320529, "miou_by_class": [0.9999599705139505, 0.8083797325501554]}, "test_metrics": {"range_doppler": {"loss": 6.34811440249905e-05, "loss_ce": 0.000126962288049981, "loss_dice": 0.0, "acc": 0.9999831269239391, "acc_by_class": [0.9999831269239391, 0.9999831269239391], "prec": 0.9712150801389983, "prec_by_class": [0.9999942887368939, 0.9424358715411028], "recall": 0.9848456013368053, "recall_by_class": [0.9999888349752509, 0.9697023676983597], "miou": 0.9577310335756437, "miou_by_class": [0.9999831238396766, 0.915478943311611], "dice": 0.9779331327974992, "dice_by_class": [0.9999915568486366, 0.9558747087463616], "confusion_matrix": [[357361989.0, 3990.0], [2041.0, 65324.0]]}, "global_acc": 0.9999831269239391, "global_prec": 0.9712150801389983, "global_dice": 0.9779331327974992, "global_recall": 0.9848456013368053, "global_miou": 0.9577310335756437, "miou_by_class": [0.9999831238396766, 0.915478943311611]}} \ No newline at end of file diff --git a/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/config.json b/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/config.json new file mode 100644 index 0000000000000000000000000000000000000000..d504d32a4abaf81f1bd5ae295d4013a2583f4ada --- /dev/null +++ b/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/config.json @@ -0,0 +1,48 @@ +{ + "model": "fcn8s", + "dataset": "Syn-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 2, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 1, + "device": "cuda:0", + "custom_loss": "ce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 1, + "ReCK_MODE": "fcn8s(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the fcn8s Syn-RED dataset.", + "distributed": false, + "name_exp": "fcn8s_e300_lr0.0001_ce" +} \ No newline at end of file diff --git a/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/results/fcn8s.pt b/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/results/fcn8s.pt new file mode 100644 index 0000000000000000000000000000000000000000..f45a5e355af5ebbb729adf32847465992376e16f --- /dev/null +++ b/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/results/fcn8s.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a15ac28b7d157db9d45f2ae47fe917dbc7f8c3b2e74a074cc244f7c71b7a886e +size 537093997 diff --git a/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/results/fcn8s_results.json b/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/results/fcn8s_results.json new file mode 100644 index 0000000000000000000000000000000000000000..423e816fd34d8c27d1438c9aff80e4c905ba68d7 --- /dev/null +++ b/models/Syn-RED/fcn8s_e300_lr0.0001_ce_1/results/fcn8s_results.json @@ -0,0 +1 @@ +{"epoch": 179, "rd_train_loss": 1.7449270671932027e-05, "train_loss": 1.7449270671932027e-05, "val_metrics": {"range_doppler": {"loss": 0.00011794316378654912, "loss_ce": 0.00023588632757309824, "loss_dice": 0.0, "acc": 0.999966060340948, "acc_by_class": [0.999966060340948, 0.999966060340948], "prec": 0.962467290400711, "prec_by_class": [0.9999790549408373, 0.9249555258605848], "recall": 0.942192206351762, "recall_by_class": [0.9999869994172219, 0.8843974132863022], "miou": 0.9125765518682352, "miou_by_class": [0.9999660549026459, 0.8251870488338245], "dice": 0.9521024576283864, "dice_by_class": [0.9999830221632507, 0.9042218930935221], "confusion_matrix": [[704113127.0, 9154.0], [14748.0, 112827.0]]}, "global_acc": 0.999966060340948, "global_prec": 0.962467290400711, "global_dice": 0.9521024576283864, "global_recall": 0.942192206351762, "global_miou": 0.9125765518682352, "miou_by_class": [0.9999660549026459, 0.8251870488338245]}, "test_metrics": {"range_doppler": {"loss": 6.38734272797592e-05, "loss_ce": 0.0001277468545595184, "loss_dice": 0.0, "acc": 0.9999707609819413, "acc_by_class": [0.9999707609819413, 0.9999707609819413], "prec": 0.9657188546503648, "prec_by_class": [0.9999834064321504, 0.931454302868579], "recall": 0.955979720718175, "recall_by_class": [0.9999873491035363, 0.9119720923328137], "miou": 0.9272938942396228, "miou_by_class": [0.9999707559555275, 0.8546170325237181], "dice": 0.9607978083562716, "dice_by_class": [0.9999853727639572, 0.9216102439485861], "confusion_matrix": [[357361458.0, 4521.0], [5930.0, 61435.0]]}, "global_acc": 0.9999707609819413, "global_prec": 0.9657188546503648, "global_dice": 0.9607978083562716, "global_recall": 0.955979720718175, "global_miou": 0.9272938942396228, "miou_by_class": [0.9999707559555275, 0.8546170325237181]}} \ No newline at end of file diff --git a/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/config.json b/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/config.json new file mode 100644 index 0000000000000000000000000000000000000000..f4cab8bda9677cb4b29151ad1f694f999b7b1ad6 --- /dev/null +++ b/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/config.json @@ -0,0 +1,48 @@ +{ + "model": "tmva_net_sv", + "dataset": "Syn-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 2, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 0, + "device": "cuda:0", + "custom_loss": "ce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 1, + "ReCK_MODE": "tmva_net_sv(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the tmva_net Syn-RED dataset.", + "distributed": false, + "name_exp": "tmva_net_sv_e300_lr0.0001_ce" +} \ No newline at end of file diff --git a/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/results/tmva_net_sv.pt b/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/results/tmva_net_sv.pt new file mode 100644 index 0000000000000000000000000000000000000000..1b6f790811fceb56287339e19904e9acde9664e8 --- /dev/null +++ b/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/results/tmva_net_sv.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f89f1ccb97442ba37040d8ebc43c6dd67e90b1a58b54162a00422c9b554249b9 +size 4665034 diff --git a/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/results/tmva_net_sv_results.json b/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/results/tmva_net_sv_results.json new file mode 100644 index 0000000000000000000000000000000000000000..9e700fd69aa5075bdae4b4fd933193070e52cfa1 --- /dev/null +++ b/models/Syn-RED/tmva_net_sv_e300_lr0.0001_ce_0/results/tmva_net_sv_results.json @@ -0,0 +1 @@ +{"epoch": 169, "rd_train_loss": 1.2266093563084723e-07, "train_loss": 1.2266093563084723e-07, "val_metrics": {"range_doppler": {"loss": 0.00015203982184175402, "loss_ce": 0.00030407964368350804, "loss_dice": 0.0, "acc": 0.9999696442962425, "acc_by_class": [0.9999696442962425, 0.9999696442962425], "prec": 0.981784056197184, "prec_by_class": [0.9999755615156126, 0.9635925508787553], "recall": 0.9325543580905915, "recall_by_class": [0.9999940777332113, 0.8651146384479718], "miou": 0.9188508108883485, "miou_by_class": [0.9999696395382819, 0.8377319822384152], "dice": 0.9558434158788987, "dice_by_class": [0.9999848145386981, 0.9117020172190993], "confusion_matrix": [[704118111.0, 4170.0], [17208.0, 110367.0]]}, "global_acc": 0.9999696442962425, "global_prec": 0.981784056197184, "global_dice": 0.9558434158788987, "global_recall": 0.9325543580905915, "global_miou": 0.9188508108883485, "miou_by_class": [0.9999696395382819, 0.8377319822384152]}, "test_metrics": {"range_doppler": {"loss": 9.511468670098111e-05, "loss_ce": 0.00019022937340196222, "loss_dice": 0.0, "acc": 0.9999806929036816, "acc_by_class": [0.9999806929036816, 0.9999806929036816], "prec": 0.9932721645216247, "prec_by_class": [0.9999830260529381, 0.9865613029903113], "recall": 0.9549754516363461, "recall_by_class": [0.999997663459733, 0.9099532398129593], "miou": 0.9493965031537668, "miou_by_class": [0.9999806895919909, 0.8988123167155425], "dice": 0.9733501739578327, "dice_by_class": [0.9999903397027716, 0.9467100082128937], "confusion_matrix": [[357365144.0, 835.0], [6066.0, 61299.0]]}, "global_acc": 0.9999806929036816, "global_prec": 0.9932721645216247, "global_dice": 0.9733501739578327, "global_recall": 0.9549754516363461, "global_miou": 0.9493965031537668, "miou_by_class": [0.9999806895919909, 0.8988123167155425]}} \ No newline at end of file diff --git a/models/Syn-RED/unet_e300_lr0.0001_ce_0/config.json b/models/Syn-RED/unet_e300_lr0.0001_ce_0/config.json new file mode 100644 index 0000000000000000000000000000000000000000..600b05c8a4e153c3f4b56e274ecbfe111ff0c883 --- /dev/null +++ b/models/Syn-RED/unet_e300_lr0.0001_ce_0/config.json @@ -0,0 +1,48 @@ +{ + "model": "unet", + "dataset": "Syn-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 2, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 0, + "device": "cuda:0", + "custom_loss": "ce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 1, + "ReCK_MODE": "unet(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the fcn8s Syn-RED dataset.", + "distributed": false, + "name_exp": "unet_e300_lr0.0001_ce" +} \ No newline at end of file diff --git a/models/Syn-RED/unet_e300_lr0.0001_ce_0/results/unet.pt b/models/Syn-RED/unet_e300_lr0.0001_ce_0/results/unet.pt new file mode 100644 index 0000000000000000000000000000000000000000..a8a476cf94f0af8eec662c5b3de3150306c20fa0 --- /dev/null +++ b/models/Syn-RED/unet_e300_lr0.0001_ce_0/results/unet.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:852944f41f46877a7e63fac0730f8913dfef139457406e49afe44b1d0d699837 +size 69127746 diff --git a/models/Syn-RED/unet_e300_lr0.0001_ce_0/results/unet_results.json b/models/Syn-RED/unet_e300_lr0.0001_ce_0/results/unet_results.json new file mode 100644 index 0000000000000000000000000000000000000000..3c7e2a2453604bd64c89f387d7fd53ed8fdee480 --- /dev/null +++ b/models/Syn-RED/unet_e300_lr0.0001_ce_0/results/unet_results.json @@ -0,0 +1 @@ +{"epoch": 284, "rd_train_loss": 1.876439281733866e-10, "train_loss": 1.876439281733866e-10, "val_metrics": {"range_doppler": {"loss": 0.0004178793460596353, "loss_ce": 0.0008357586921192706, "loss_dice": 0.0, "acc": 0.9999376726887113, "acc_by_class": [0.9999376726887113, 0.9999376726887113], "prec": 0.9204360381134005, "prec_by_class": [0.9999653926127768, 0.840906683614024], "recall": 0.9044815293763986, "recall_by_class": [0.9999722690212668, 0.8089907897315305], "miou": 0.8507720214218983, "miou_by_class": [0.9999376635533772, 0.7016063792904195], "dice": 0.9123044321367604, "dice_by_class": [0.9999688258052003, 0.8246400384683205], "confusion_matrix": [[704102755.0, 19526.0], [24368.0, 103207.0]]}, "global_acc": 0.9999376726887113, "global_prec": 0.9204360381134005, "global_dice": 0.9123044321367604, "global_recall": 0.9044815293763986, "global_miou": 0.8507720214218983, "miou_by_class": [0.9999376635533772, 0.7016063792904195]}, "test_metrics": {"range_doppler": {"loss": 0.00041044523823074996, "loss_ce": 0.0008208904764614999, "loss_dice": 0.0, "acc": 0.9999325021003077, "acc_by_class": [0.9999325021003077, 0.9999325021003077], "prec": 0.9043240039855899, "prec_by_class": [0.9999699857264304, 0.8086780222447494], "recall": 0.9203701777129758, "recall_by_class": [0.9999625034256548, 0.8407778520002969], "miou": 0.8506069935501339, "miou_by_class": [0.9999324914028742, 0.7012814956973936], "dice": 0.9121909132704418, "dice_by_class": [0.9999662395620459, 0.8244155869788377], "confusion_matrix": [[357352579.0, 13400.0], [10726.0, 56639.0]]}, "global_acc": 0.9999325021003077, "global_prec": 0.9043240039855899, "global_dice": 0.9121909132704418, "global_recall": 0.9203701777129758, "global_miou": 0.8506069935501339, "miou_by_class": [0.9999324914028742, 0.7012814956973936]}} \ No newline at end of file diff --git a/models/Syn-RED/vit_e300_lr0.0001_ce_0/config.json b/models/Syn-RED/vit_e300_lr0.0001_ce_0/config.json new file mode 100644 index 0000000000000000000000000000000000000000..4b624df8a4cabcecfe7c9e812a46032cce35e80d --- /dev/null +++ b/models/Syn-RED/vit_e300_lr0.0001_ce_0/config.json @@ -0,0 +1,48 @@ +{ + "model": "vit", + "dataset": "Syn-RED", + "task_name": "Segmentation", + "cmplx_flag": false, + "process_signal": true, + "annot_format": "light_frame", + "annot_type": "dense", + "w_size": 128, + "h_size": 1024, + "nb_classes": 2, + "nb_input_channels": 1, + "lmf_chains": 1, + "lmf_channels": 1, + "lmf_layers": 1, + "lmf_coefs": "tay_mf", + "ldc_channels": 1, + "ldc_orders": 3, + "nb_doppler": 128, + "activation": "None", + "bias": false, + "nb_epochs": 300, + "batch_size": 8, + "lr": 0.0001, + "lr_step": 20, + "schedular": "cos", + "Tmax": 300, + "loss_step": 100, + "val_step": 2000, + "viz_step": 4000, + "torch_seed": 42, + "numpy_seed": 42, + "version": 0, + "device": "cuda:0", + "custom_loss": "ce", + "transformations": "hflip,vflip", + "norm_type": "tvt", + "shuffle": true, + "num_workers": 1, + "ReCK_MODE": "vit(adamw)", + "ReCK_Module": "0 modules", + "scale_factor": 0.1, + "num_heads": 1, + "pin_mem": true, + "comments": "This is a test to train the vit Syn-RED dataset.", + "distributed": false, + "name_exp": "vit_e300_lr0.0001_ce" +} \ No newline at end of file diff --git a/models/Syn-RED/vit_e300_lr0.0001_ce_0/results/vit.pt b/models/Syn-RED/vit_e300_lr0.0001_ce_0/results/vit.pt new file mode 100644 index 0000000000000000000000000000000000000000..dde4f1c941f5e6023e55a245af854de74d3e906d --- /dev/null +++ b/models/Syn-RED/vit_e300_lr0.0001_ce_0/results/vit.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01dc853acd50efbf2b01b24a2a7d06a4db13832b0912c85f203a06e4c3189136 +size 5566098 diff --git a/models/Syn-RED/vit_e300_lr0.0001_ce_0/results/vit_results.json b/models/Syn-RED/vit_e300_lr0.0001_ce_0/results/vit_results.json new file mode 100644 index 0000000000000000000000000000000000000000..d895a46c0d3802cb6ca40c712beaf89d54b4768e --- /dev/null +++ b/models/Syn-RED/vit_e300_lr0.0001_ce_0/results/vit_results.json @@ -0,0 +1 @@ +{"epoch": 211, "rd_train_loss": 1.2536600024759537e-06, "train_loss": 1.2536600024759537e-06, "val_metrics": {"range_doppler": {"loss": 0.00012933964899275452, "loss_ce": 0.00025867929798550904, "loss_dice": 0.0, "acc": 0.9999684998160653, "acc_by_class": [0.9999684998160653, 0.9999684998160653], "prec": 0.9771061718189211, "prec_by_class": [0.9999760343859738, 0.9542363092518684], "recall": 0.9338586639206614, "recall_by_class": [0.9999924601164553, 0.8677248677248677], "miou": 0.9165129491567222, "miou_by_class": [0.9999684948638192, 0.8330574034496252], "dice": 0.9544554659438129, "dice_by_class": [0.9999842421837623, 0.9089266897038637], "confusion_matrix": [[704116972.0, 5309.0], [16875.0, 110700.0]]}, "global_acc": 0.9999684998160653, "global_prec": 0.9771061718189211, "global_dice": 0.9544554659438129, "global_recall": 0.9338586639206614, "global_miou": 0.9165129491567222, "miou_by_class": [0.9999684948638192, 0.8330574034496252]}, "test_metrics": {"range_doppler": {"loss": 0.00011070585605921224, "loss_ce": 0.00022141171211842448, "loss_dice": 0.0, "acc": 0.9999771397936505, "acc_by_class": [0.9999771397936505, 0.9999771397936505], "prec": 0.9845307295174774, "prec_by_class": [0.999982595081614, 0.969078863953341], "recall": 0.953830863417503, "recall_by_class": [0.9999945406107055, 0.9076671862243004], "miou": 0.9410483521179923, "miou_by_class": [0.9999771358823578, 0.8821195683536268], "dice": 0.9686784067315604, "dice_by_class": [0.9999885628104854, 0.9373682506526354], "confusion_matrix": [[357364028.0, 1951.0], [6220.0, 61145.0]]}, "global_acc": 0.9999771397936505, "global_prec": 0.9845307295174774, "global_dice": 0.9686784067315604, "global_recall": 0.953830863417503, "global_miou": 0.9410483521179923, "miou_by_class": [0.9999771358823578, 0.8821195683536268]}} \ No newline at end of file diff --git a/models/deeplabv3plus.py b/models/deeplabv3plus.py new file mode 100644 index 0000000000000000000000000000000000000000..3fc8210d7d96f0b6c1adbe9ca1f6a9f191e71c42 --- /dev/null +++ b/models/deeplabv3plus.py @@ -0,0 +1,516 @@ +# from https://github.com/VainF/DeepLabV3Plus-Pytorch/tree/master +import torch +import torch.nn as nn +from torch.nn import functional as F +from collections import OrderedDict + +class IntermediateLayerGetter(nn.ModuleDict): + """ + Module wrapper that returns intermediate layers from a model + + It has a strong assumption that the modules have been registered + into the model in the same order as they are used. + This means that one should **not** reuse the same nn.Module + twice in the forward if you want this to work. + + Additionally, it is only able to query submodules that are directly + assigned to the model. So if `model` is passed, `model.feature1` can + be returned, but not `model.feature1.layer2`. + + Arguments: + model (nn.Module): model on which we will extract the features + return_layers (Dict[name, new_name]): a dict containing the names + of the modules for which the activations will be returned as + the key of the dict, and the value of the dict is the name + of the returned activation (which the user can specify). + + Examples:: + + >>> m = torchvision.models.resnet18(pretrained=True) + >>> # extract layer1 and layer3, giving as names `feat1` and feat2` + >>> new_m = torchvision.models._utils.IntermediateLayerGetter(m, + >>> {'layer1': 'feat1', 'layer3': 'feat2'}) + >>> out = new_m(torch.rand(1, 3, 224, 224)) + >>> print([(k, v.shape) for k, v in out.items()]) + >>> [('feat1', torch.Size([1, 64, 56, 56])), + >>> ('feat2', torch.Size([1, 256, 14, 14]))] + """ + def __init__(self, model, return_layers, hrnet_flag=False): + if not set(return_layers).issubset([name for name, _ in model.named_children()]): + raise ValueError("return_layers are not present in model") + + self.hrnet_flag = hrnet_flag + + orig_return_layers = return_layers + return_layers = {k: v for k, v in return_layers.items()} + layers = OrderedDict() + for name, module in model.named_children(): + layers[name] = module + if name in return_layers: + del return_layers[name] + if not return_layers: + break + + super(IntermediateLayerGetter, self).__init__(layers) + self.return_layers = orig_return_layers + + def forward(self, x): + out = OrderedDict() + for name, module in self.named_children(): + if self.hrnet_flag and name.startswith('transition'): # if using hrnet, you need to take care of transition + if name == 'transition1': # in transition1, you need to split the module to two streams first + x = [trans(x) for trans in module] + else: # all other transition is just an extra one stream split + x.append(module(x[-1])) + else: # other models (ex:resnet,mobilenet) are convolutions in series. + x = module(x) + + if name in self.return_layers: + out_name = self.return_layers[name] + if name == 'stage4' and self.hrnet_flag: # In HRNetV2, we upsample and concat all outputs streams together + output_h, output_w = x[0].size(2), x[0].size(3) # Upsample to size of highest resolution stream + x1 = F.interpolate(x[1], size=(output_h, output_w), mode='bilinear', align_corners=False) + x2 = F.interpolate(x[2], size=(output_h, output_w), mode='bilinear', align_corners=False) + x3 = F.interpolate(x[3], size=(output_h, output_w), mode='bilinear', align_corners=False) + x = torch.cat([x[0], x1, x2, x3], dim=1) + out[out_name] = x + else: + out[out_name] = x + return out + +class _SimpleSegmentationModel(nn.Module): + def __init__(self, backbone, classifier): + super(_SimpleSegmentationModel, self).__init__() + self.backbone = backbone + self.classifier = classifier + + # lt@20240406 reduce resolution + # self.pool0 = nn.MaxPool2d(2, stride=2, ceil_mode=True) + + def forward(self, x): + # lt@20240406 reduce resolution + # x = self.pool0(x) + # lt@20240408 add resolution + # x = F.interpolate(x, scale_factor=2, mode='bilinear', align_corners=True) + + input_shape = x.shape[-2:] + features = self.backbone(x) + x = self.classifier(features) + x = F.interpolate(x, size=input_shape, mode='bilinear', align_corners=False) + + # lt@20240406 recover resolution + # x = F.interpolate(x, scale_factor=2, mode='bilinear', align_corners=True) + # lt@20240408 add resolution + # x = F.interpolate(x, scale_factor=0.5, mode='bilinear', align_corners=True) + + return x + +class DeepLabV3(_SimpleSegmentationModel): + """ + Implements DeepLabV3 model from + `"Rethinking Atrous Convolution for Semantic Image Segmentation" + `_. + + Arguments: + backbone (nn.Module): the network used to compute the features for the model. + The backbone should return an OrderedDict[Tensor], with the key being + "out" for the last feature map used, and "aux" if an auxiliary classifier + is used. + classifier (nn.Module): module that takes the "out" element returned from + the backbone and returns a dense prediction. + aux_classifier (nn.Module, optional): auxiliary classifier used during training + """ + pass + +class DeepLabHeadV3Plus(nn.Module): + def __init__(self, in_channels, low_level_channels, num_classes, aspp_dilate=[12, 24, 36]): + super(DeepLabHeadV3Plus, self).__init__() + self.project = nn.Sequential( + nn.Conv2d(low_level_channels, 48, 1, bias=False), + nn.BatchNorm2d(48), + nn.ReLU(inplace=True), + ) + + self.aspp = ASPP(in_channels, aspp_dilate) + + self.classifier = nn.Sequential( + nn.Conv2d(304, 256, 3, padding=1, bias=False), + nn.BatchNorm2d(256), + nn.ReLU(inplace=True), + nn.Conv2d(256, num_classes, 1) + ) + self._init_weight() + + def forward(self, feature): + low_level_feature = self.project( feature['low_level'] ) + output_feature = self.aspp(feature['out']) + output_feature = F.interpolate(output_feature, size=low_level_feature.shape[2:], mode='bilinear', align_corners=False) + return self.classifier( torch.cat( [ low_level_feature, output_feature ], dim=1 ) ) + + def _init_weight(self): + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight) + elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + +class DeepLabHead(nn.Module): + def __init__(self, in_channels, num_classes, aspp_dilate=[12, 24, 36]): + super(DeepLabHead, self).__init__() + + self.classifier = nn.Sequential( + ASPP(in_channels, aspp_dilate), + nn.Conv2d(256, 256, 3, padding=1, bias=False), + nn.BatchNorm2d(256), + nn.ReLU(inplace=True), + nn.Conv2d(256, num_classes, 1) + ) + self._init_weight() + + def forward(self, feature): + return self.classifier( feature['out'] ) + + def _init_weight(self): + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight) + elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + +class AtrousSeparableConvolution(nn.Module): + """ Atrous Separable Convolution + """ + def __init__(self, in_channels, out_channels, kernel_size, + stride=1, padding=0, dilation=1, bias=True): + super(AtrousSeparableConvolution, self).__init__() + self.body = nn.Sequential( + # Separable Conv + nn.Conv2d( in_channels, in_channels, kernel_size=kernel_size, stride=stride, padding=padding, dilation=dilation, bias=bias, groups=in_channels ), + # PointWise Conv + nn.Conv2d( in_channels, out_channels, kernel_size=1, stride=1, padding=0, bias=bias), + ) + + self._init_weight() + + def forward(self, x): + return self.body(x) + + def _init_weight(self): + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight) + elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + +class ASPPConv(nn.Sequential): + def __init__(self, in_channels, out_channels, dilation): + modules = [ + nn.Conv2d(in_channels, out_channels, 3, padding=dilation, dilation=dilation, bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True) + ] + super(ASPPConv, self).__init__(*modules) + +class ASPPPooling(nn.Sequential): + def __init__(self, in_channels, out_channels): + super(ASPPPooling, self).__init__( + nn.AdaptiveAvgPool2d(1), + nn.Conv2d(in_channels, out_channels, 1, bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True)) + + def forward(self, x): + size = x.shape[-2:] + x = super(ASPPPooling, self).forward(x) + return F.interpolate(x, size=size, mode='bilinear', align_corners=False) + +class ASPP(nn.Module): + def __init__(self, in_channels, atrous_rates): + super(ASPP, self).__init__() + out_channels = 256 + modules = [] + modules.append(nn.Sequential( + nn.Conv2d(in_channels, out_channels, 1, bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True))) + + rate1, rate2, rate3 = tuple(atrous_rates) + modules.append(ASPPConv(in_channels, out_channels, rate1)) + modules.append(ASPPConv(in_channels, out_channels, rate2)) + modules.append(ASPPConv(in_channels, out_channels, rate3)) + modules.append(ASPPPooling(in_channels, out_channels)) + + self.convs = nn.ModuleList(modules) + + self.project = nn.Sequential( + nn.Conv2d(5 * out_channels, out_channels, 1, bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True), + nn.Dropout(0.1),) + + def forward(self, x): + res = [] + for conv in self.convs: + res.append(conv(x)) + res = torch.cat(res, dim=1) + return self.project(res) + + + +def convert_to_separable_conv(module): + new_module = module + if isinstance(module, nn.Conv2d) and module.kernel_size[0]>1: + new_module = AtrousSeparableConvolution(module.in_channels, + module.out_channels, + module.kernel_size, + module.stride, + module.padding, + module.dilation, + module.bias) + for name, child in module.named_children(): + new_module.add_module(name, convert_to_separable_conv(child)) + return new_module + + +def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): + """3x3 convolution with padding""" + return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, + padding=dilation, groups=groups, bias=False, dilation=dilation) + + +def conv1x1(in_planes, out_planes, stride=1): + """1x1 convolution""" + return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) + + +class BasicBlock(nn.Module): + expansion = 1 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None): + super(BasicBlock, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + if groups != 1 or base_width != 64: + raise ValueError('BasicBlock only supports groups=1 and base_width=64') + if dilation > 1: + raise NotImplementedError("Dilation > 1 not supported in BasicBlock") + # Both self.conv1 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv3x3(inplanes, planes, stride) + self.bn1 = norm_layer(planes) + self.relu = nn.ReLU(inplace=True) + self.conv2 = conv3x3(planes, planes) + self.bn2 = norm_layer(planes) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class Bottleneck(nn.Module): + expansion = 4 + + def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, + base_width=64, dilation=1, norm_layer=None): + super(Bottleneck, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + width = int(planes * (base_width / 64.)) * groups + # Both self.conv2 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv1x1(inplanes, width) + self.bn1 = norm_layer(width) + self.conv2 = conv3x3(width, width, stride, groups, dilation) + self.bn2 = norm_layer(width) + self.conv3 = conv1x1(width, planes * self.expansion) + self.bn3 = norm_layer(planes * self.expansion) + self.relu = nn.ReLU(inplace=True) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class ResNet(nn.Module): + + def __init__(self, n_frames, block, layers, num_classes=1000, zero_init_residual=False, + groups=1, width_per_group=64, replace_stride_with_dilation=None, + norm_layer=None): + super(ResNet, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + self._norm_layer = norm_layer + + self.inplanes = 64 + self.dilation = 1 + if replace_stride_with_dilation is None: + # each element in the tuple indicates if we should replace + # the 2x2 stride with a dilated convolution instead + replace_stride_with_dilation = [False, False, False] + if len(replace_stride_with_dilation) != 3: + raise ValueError("replace_stride_with_dilation should be None " + "or a 3-element tuple, got {}".format(replace_stride_with_dilation)) + self.groups = groups + self.base_width = width_per_group + self.conv1 = nn.Conv2d(n_frames, self.inplanes, kernel_size=7, stride=2, padding=3, + bias=False) + self.bn1 = norm_layer(self.inplanes) + self.relu = nn.ReLU(inplace=True) + self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) + # the actual output channels are 256 + self.layer1 = self._make_layer(block, 64, layers[0]) + self.layer2 = self._make_layer(block, 128, layers[1], stride=2, + dilate=replace_stride_with_dilation[0]) + self.layer3 = self._make_layer(block, 256, layers[2], stride=2, + dilate=replace_stride_with_dilation[1]) + self.layer4 = self._make_layer(block, 512, layers[3], stride=2, + dilate=replace_stride_with_dilation[2]) + self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) + self.fc = nn.Linear(512 * block.expansion, num_classes) + + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') + elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + + # Zero-initialize the last BN in each residual branch, + # so that the residual branch starts with zeros, and each residual block behaves like an identity. + # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677 + if zero_init_residual: + for m in self.modules(): + if isinstance(m, Bottleneck): + nn.init.constant_(m.bn3.weight, 0) + elif isinstance(m, BasicBlock): + nn.init.constant_(m.bn2.weight, 0) + + def _make_layer(self, block, planes, blocks, stride=1, dilate=False): + norm_layer = self._norm_layer + downsample = None + previous_dilation = self.dilation + if dilate: + # dilation rate equals to the stride product of previous layers + self.dilation *= stride + stride = 1 + if stride != 1 or self.inplanes != planes * block.expansion: + downsample = nn.Sequential( + conv1x1(self.inplanes, planes * block.expansion, stride), + norm_layer(planes * block.expansion), + ) + + layers = [] + # Q: the dilation rate of the first layer remains the same with as the privious block? + layers.append(block(self.inplanes, planes, stride, downsample, self.groups, + self.base_width, previous_dilation, norm_layer)) + self.inplanes = planes * block.expansion + for _ in range(1, blocks): + layers.append(block(self.inplanes, planes, groups=self.groups, + base_width=self.base_width, dilation=self.dilation, + norm_layer=norm_layer)) + + return nn.Sequential(*layers) + + def forward(self, x): + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + x = self.maxpool(x) + + x = self.layer1(x) + x = self.layer2(x) + x = self.layer3(x) + x = self.layer4(x) + + x = self.avgpool(x) + x = torch.flatten(x, 1) + x = self.fc(x) + + return x + + +def _resnet(arch, n_frames, block, layers, pretrained, progress, **kwargs): + model = ResNet(n_frames, block, layers, **kwargs) + return model + +def resnet101(n_frames, pretrained=False, progress=True, **kwargs): + r"""ResNet-101 model from + `"Deep Residual Learning for Image Recognition" `_ + + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet101', n_frames, Bottleneck, [3, 4, 23, 3], pretrained, progress, + **kwargs) + + +def _segm_resnet(name, backbone_name, num_classes, n_frames, output_stride, pretrained_backbone): + + if output_stride==8: + replace_stride_with_dilation=[False, True, True] + aspp_dilate = [12, 24, 36] + else: + replace_stride_with_dilation=[False, False, True] + aspp_dilate = [6, 12, 18] + + backbone = resnet101(n_frames, pretrained=pretrained_backbone, + replace_stride_with_dilation=replace_stride_with_dilation) + + inplanes = 2048 + low_level_planes = 256 + + return_layers = {'layer4': 'out', 'layer1': 'low_level'} + classifier = DeepLabHeadV3Plus(inplanes, low_level_planes, num_classes, aspp_dilate) + backbone = IntermediateLayerGetter(backbone, return_layers=return_layers) + + model = DeepLabV3(backbone, classifier) + return model + +def DeepLabV3Plus_Res101(n_classes=21, n_frames=5, output_stride=8, pretrained_backbone=False): + """Constructs a DeepLabV3+ model with a ResNet-101 backbone. + + Args: + num_classes (int): number of classes. + output_stride (int): output stride for deeplab. + pretrained_backbone (bool): If True, use the pretrained backbone. + """ + return _segm_resnet('deeplabv3plus', 'resnet101', n_classes, n_frames, output_stride=output_stride, pretrained_backbone=pretrained_backbone) \ No newline at end of file diff --git a/models/echmo.py b/models/echmo.py new file mode 100644 index 0000000000000000000000000000000000000000..efcd35b3ef448a4bd34d446a287dfaa0a96ebafa --- /dev/null +++ b/models/echmo.py @@ -0,0 +1,574 @@ +""" +EchMo Model Implementation +End-to-End Radar Echo Segmentation Model +""" + +import os +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.nn.init as init +import scipy.io as scio + + +# ==================== Utility Functions ==================== +def complex_std(x, epsilon=1e-5): + mu_R = x.real.mean(dim=3, keepdim=True).detach() + mu_I = x.imag.mean(dim=3, keepdim=True).detach() + x_R = x.real - mu_R + x_I = x.imag - mu_I + sigma_R = torch.sqrt(torch.var(x.real, dim=3, keepdim=True, unbiased=False) + epsilon) + sigma_I = torch.sqrt(torch.var(x.imag, dim=3, keepdim=True, unbiased=False) + epsilon) + x_R /= sigma_R + x_I /= sigma_I + return x_R + 1j * x_I + + +def complex_double2float(x): + x_r = x.real.float() + x_i = x.imag.float() + return x_r + 1j * x_i + + +def filter_coef_loader(path, coef_type=None): + coef = scio.loadmat(os.path.join(path, 's_tx.mat'))['s_tx'] + coef = torch.tensor(coef) + + if coef_type == 'ori_mf': + coef = complex_double2float(torch.conj(coef)) + zero = torch.complex(torch.zeros([1, 1], dtype=torch.float32), torch.zeros([1, 1], dtype=torch.float32)) + coef = torch.cat((zero, coef), dim=1) + return coef + elif coef_type == 'tay_mf': + win = scio.loadmat(os.path.join(path, 'w_taylor.mat'))['w_taylor'] + elif coef_type == 'che_mf': + win = scio.loadmat(os.path.join(path, 'w_chebyshev.mat'))['w_chebyshev'] + elif coef_type == 'ham_mf': + win = scio.loadmat(os.path.join(path, 'w_hamming.mat'))['w_hamming'] + elif coef_type == 'han_mf': + win = scio.loadmat(os.path.join(path, 'w_hanning.mat'))['w_hanning'] + elif coef_type == 'black_mf': + win = scio.loadmat(os.path.join(path, 'w_blackman.mat'))['w_blackman'] + elif coef_type == 'cos_mf': + win = scio.loadmat(os.path.join(path, 'w_cosine.mat'))['w_cosine'] + else: + win = scio.loadmat(os.path.join(path, 'w_taylor.mat'))['w_taylor'] + + win = torch.permute(torch.tensor(win), [1, 0]) + coef = complex_double2float(torch.conj(coef * win)) + zero = torch.complex(torch.zeros([1, 1], dtype=torch.float32), torch.zeros([1, 1], dtype=torch.float32)) + coef = torch.cat((zero, coef), dim=1) + return coef + + +# ==================== Model Components ==================== +class ComplexBatchNorm2d(nn.Module): + def __init__(self, num_features): + super().__init__() + self.bn_real = nn.BatchNorm2d(num_features) + self.bn_imag = nn.BatchNorm2d(num_features) + + def forward(self, x): + return torch.complex(self.bn_real(x.real), self.bn_imag(x.imag)) + + +class ComplexReLU(nn.Module): + def __init__(self, activation='leaky_relu'): + super(ComplexReLU, self).__init__() + self.activation = activation + + def forward(self, input): + if self.activation == 'relu': + return nn.ReLU()(input.real) + 1j * nn.ReLU()(input.imag) + elif self.activation == 'leaky_relu': + return F.leaky_relu(input.real) + 1j * F.leaky_relu(input.imag) + elif self.activation == 'celu': + return F.celu(input.real) + 1j * F.celu(input.imag) + else: + return input + + +class DoubleConvBlock(nn.Module): + def __init__(self, in_ch, out_ch, k_size, pad, dil): + super().__init__() + self.block = nn.Sequential( + nn.Conv2d(in_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm2d(out_ch), + nn.LeakyReLU(inplace=True), + nn.Conv2d(out_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm2d(out_ch), + nn.LeakyReLU(inplace=True) + ) + + def forward(self, x): + return self.block(x) + + +class Double3DConvBlock(nn.Module): + def __init__(self, in_ch, out_ch, k_size, pad, dil): + super().__init__() + self.block = nn.Sequential( + nn.Conv3d(in_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm3d(out_ch), + nn.LeakyReLU(inplace=True), + nn.Conv3d(out_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm3d(out_ch), + nn.LeakyReLU(inplace=True) + ) + + def forward(self, x): + return self.block(x) + + +class ConvBlock(nn.Module): + def __init__(self, in_ch, out_ch, k_size, pad, dil): + super().__init__() + self.block = nn.Sequential( + nn.Conv2d(in_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm2d(out_ch), + nn.LeakyReLU(inplace=True) + ) + + def forward(self, x): + return self.block(x) + + +class PeakConv2D(nn.Module): + def __init__(self, in_ch, out_ch, bias, refer_band, guard_band_dop, guard_band, signal_type): + super(PeakConv2D, self).__init__() + self.signal_type = signal_type + if self.signal_type in ('range_doppler', 'angle_doppler'): + self.guard_band = (guard_band_dop, guard_band_dop) + self.padding = (self.guard_band[1] + refer_band, + self.guard_band[1] + refer_band, + self.guard_band[0] + refer_band, + self.guard_band[0] + refer_band) + else: + self.guard_band = (guard_band, guard_band) + self.padding = (self.guard_band[1] + refer_band, + self.guard_band[1] + refer_band, + self.guard_band[0] + refer_band, + self.guard_band[0] + refer_band) + self.refer_band = refer_band + self.kernel_size = (self.guard_band[0] + self.guard_band[1] + self.refer_band * 2), 4 + self.stride = self.kernel_size + self.zero_padding = nn.ZeroPad2d(self.padding) + self.bias = bias + self.pc_strd = 1 + self.peak_conv = nn.Conv2d(in_ch, out_ch, + kernel_size=self.kernel_size, + padding=0, + stride=self.stride, + bias=self.bias) + + def forward(self, x): + h, w = x.shape[2], x.shape[3] + rb = self.refer_band + gb = self.guard_band + k_pk = self.kernel_size + N = k_pk[0] * k_pk[1] + dtype = x.data.type() + b = x.size(0) + + x = self.zero_padding(x) + p_r = self._get_p_r(b, h, w, N, dtype) + x_r = self._sample_x(x, p_r, N) + p_c = self._get_p_c(b, h, w, N, dtype) + x_c = self._sample_x(x, p_c, N) + x_prf = x_c - x_r + x_prf = self._reshape_x_prf(k_pk[0], k_pk[1], x_prf) + out = self.peak_conv(x_prf) + return out + + def _get_p_c(self, b, h, w, N, dtype): + p_c_x, p_c_y = torch.meshgrid( + torch.arange(self.padding[2], h * self.pc_strd + self.padding[2], self.pc_strd), + torch.arange(self.padding[0], w * self.pc_strd + self.padding[0], self.pc_strd), indexing='ij') + p_c_x = torch.flatten(p_c_x).view(1, 1, h, w).repeat(1, N, 1, 1) + p_c_y = torch.flatten(p_c_y).view(1, 1, h, w).repeat(1, N, 1, 1) + p_c = torch.cat([p_c_x, p_c_y], 1).type(dtype) + p_c = p_c.repeat(b, 1, 1, 1) + return p_c + + def _gen_prf_grid(self, rb, gb, N, dtype): + h_t = -(rb + gb[0]) + h_d = rb + gb[0] + w_l = -(rb + gb[1]) + w_r = rb + gb[1] + w_prf = (rb + gb[1]) * 2 + 1 + h_prf = (rb + gb[0]) * 2 + 1 + + prf_x_idx, prf_y_idx = torch.meshgrid( + torch.arange(h_t, h_d + 1), + torch.arange(w_l, w_r + 1), indexing='ij') + + prf_xt = prf_x_idx[0:rb] + prf_xr = prf_x_idx[rb:(h_prf - 2 * rb + 1), (w_prf - rb):w_prf] + prf_xd = prf_x_idx[(h_prf - rb):h_prf] + prf_xl = prf_x_idx[rb:(h_prf - 2 * rb + 1), 0:rb] + prf_x = torch.cat([torch.flatten(prf_xt), + torch.flatten(prf_xr), + torch.flatten(prf_xd), + torch.flatten(prf_xl)], 0) + prf_yt = prf_y_idx[0:rb] + prf_yr = prf_y_idx[rb:(h_prf - 2 * rb + 1), (w_prf - rb):w_prf] + prf_yd = prf_y_idx[(h_prf - rb):h_prf] + prf_yl = prf_y_idx[rb:(h_prf - 2 * rb + 1), 0:rb] + prf_y = torch.cat([torch.flatten(prf_yt), + torch.flatten(prf_yr), + torch.flatten(prf_yd), + torch.flatten(prf_yl)], 0) + + prf = torch.cat([prf_x, prf_y], 0) + prf = prf.view(1, 2 * N, 1, 1).type(dtype) + return prf + + def _get_p_r(self, b, h, w, N, dtype): + rb = self.refer_band + gb = self.guard_band + prf = self._gen_prf_grid(rb, gb, N, dtype) + p_c = self._get_p_c(b, h, w, N, dtype) + p_r = p_c + prf + return p_r + + def _sample_x(self, x_pad, p, N): + p = p.contiguous().permute(0, 2, 3, 1).floor() + b, h, w, _ = p.size() + h_pad = x_pad.size(2) + w_pad = x_pad.size(3) + c = x_pad.size(1) + x_pad = x_pad.contiguous().view(b, c, -1) + index = p[..., :N] * w_pad + p[..., N:] + index = index.contiguous().unsqueeze(dim=1).expand(-1, c, -1, -1, -1).contiguous().view(b, c, -1) + index = index.long().to(x_pad.device) + x_r = x_pad.gather(dim=-1, index=index).contiguous().view(b, c, h, w, N) + return x_r + + @staticmethod + def _reshape_x_prf(k_h, k_w, x_prf): + b, c, h, w, N = x_prf.size() + x_prf = torch.cat([x_prf[..., s:s + k_w].contiguous().view(b, c, h, w * k_w) for s in range(0, N, k_w)], dim=-1) + x_prf = x_prf.contiguous().view(b, c, h * k_h, w * k_w) + return x_prf + + +class DoublePeakConv2D(nn.Module): + def __init__(self, in_ch, out_ch, bias, rb, gb_dop, gb, sig): + super(DoublePeakConv2D, self).__init__() + self.bias = bias + self.refer_band = rb + self.guard_band_dop = gb_dop + self.guard_band = gb + self.signal_type = sig + self.pk_conv1 = PeakConv2D(in_ch, out_ch, bias=self.bias, + refer_band=self.refer_band, + guard_band_dop=self.guard_band_dop, + guard_band=self.guard_band, + signal_type=self.signal_type) + self.bn1 = nn.BatchNorm2d(out_ch) + self.act1 = nn.LeakyReLU(inplace=True) + self.pk_conv2 = PeakConv2D(out_ch, out_ch, bias=self.bias, + refer_band=self.refer_band, + guard_band_dop=self.guard_band_dop, + guard_band=self.guard_band, + signal_type=self.signal_type) + self.bn2 = nn.BatchNorm2d(out_ch) + self.act2 = nn.LeakyReLU(inplace=True) + + def forward(self, x): + x = self.pk_conv1(x) + x = self.bn1(x) + x = self.act1(x) + x = self.pk_conv2(x) + x = self.bn2(x) + x = self.act2(x) + return x + + +class ASPPBlock(nn.Module): + def __init__(self, in_ch, out_ch, shape): + super().__init__() + self.shape = shape + self.global_avg_pool = nn.AvgPool2d(self.shape) + self.conv1_1x1 = nn.Conv2d(in_ch, out_ch, kernel_size=1, padding=0, dilation=1) + self.single_conv_block1_1x1 = ConvBlock(in_ch, out_ch, k_size=1, pad=0, dil=1) + self.single_conv_block1_3x3 = ConvBlock(in_ch, out_ch, k_size=3, pad=6, dil=6) + self.single_conv_block2_3x3 = ConvBlock(in_ch, out_ch, k_size=3, pad=12, dil=12) + self.single_conv_block3_3x3 = ConvBlock(in_ch, out_ch, k_size=3, pad=18, dil=18) + + def forward(self, x): + x1 = F.interpolate(self.global_avg_pool(x), size=self.shape, align_corners=False, mode='bilinear') + x1 = self.conv1_1x1(x1) + x2 = self.single_conv_block1_1x1(x) + x3 = self.single_conv_block1_3x3(x) + x4 = self.single_conv_block2_3x3(x) + x5 = self.single_conv_block3_3x3(x) + x_cat = torch.cat((x2, x3, x4, x5, x1), 1) + return x_cat + + +class EncodingBranch(nn.Module): + def __init__(self, signal_type, n_frames, in_ch=1): + super().__init__() + self.signal_type = signal_type + self.n_frames = n_frames + self.in_ch = in_ch + self.double_3dconv_block1 = Double3DConvBlock(in_ch=self.in_ch, out_ch=32, + k_size=(1+n_frames//2, 3, 3), + pad=(0, 1, 1), dil=1) + self.doppler_max_pool = nn.MaxPool2d(2, stride=(1, 2)) + self.max_pool = nn.MaxPool2d(2, stride=2) + self.double_pkc_block = DoublePeakConv2D(in_ch=32, out_ch=64, + bias=True, rb=1, gb_dop=1, gb=1, sig=self.signal_type) + self.single_conv_block1_1x1 = ConvBlock(in_ch=64, out_ch=128, k_size=1, pad=0, dil=1) + + def forward(self, x): + x1 = self.double_3dconv_block1(x) + x1 = torch.squeeze(x1, 2) + x1_pad = F.pad(x1, (0, 0, 0, 0), "constant", 0) + x1_down = self.max_pool(x1_pad) + x2 = self.double_pkc_block(x1_down) + x2_pad = F.pad(x2, (0, 0, 0, 1), "constant", 0) + x2_down = self.doppler_max_pool(x2_pad) + x3 = self.single_conv_block1_1x1(x2_down) + return x2_down, x3 + + +class PKCIn4ANY(nn.Module): + def __init__(self, n_classes, n_frames, in_ch, w, h): + super().__init__() + self.n_classes = n_classes + self.n_frames = n_frames + self.in_ch = in_ch + self.rd_shape = (int(w//2), int(h//4)) + + self.rd_encoding_branch = EncodingBranch('range_doppler', self.n_frames, self.in_ch) + self.rd_aspp_block = ASPPBlock(in_ch=64, out_ch=128, shape=self.rd_shape) + self.rd_single_conv_block1_1x1 = ConvBlock(in_ch=640, out_ch=128, k_size=1, pad=0, dil=1) + + self.rd_upconv1 = nn.ConvTranspose2d(256, 128, (2, 2), stride=(2, 2)) + self.rd_double_conv_block1 = DoubleConvBlock(in_ch=128, out_ch=128, k_size=3, pad=1, dil=1) + self.rd_upconv2 = nn.ConvTranspose2d(128, 128, (1, 2), stride=(1, 2)) + self.rd_double_conv_block2 = DoubleConvBlock(in_ch=128, out_ch=128, k_size=3, pad=1, dil=1) + self.rd_final = nn.Conv2d(in_channels=128, out_channels=n_classes, kernel_size=1) + + def forward(self, x_rd): + rd_features, rd_latent = self.rd_encoding_branch(x_rd) + x2_rd = self.rd_aspp_block(rd_features) + x2_rd = self.rd_single_conv_block1_1x1(x2_rd) + x4_rd = torch.cat((x2_rd, rd_latent), 1) + x4_rd = self.rd_upconv1(x4_rd) + x4_rd = self.rd_double_conv_block1(x4_rd) + x4_rd = self.rd_upconv2(x4_rd) + x4_rd = self.rd_double_conv_block2(x4_rd) + x4_rd = self.rd_final(x4_rd) + return x4_rd + + +def _init_translator_weights(m): + if isinstance(m, nn.Linear): + torch.nn.init.xavier_uniform_(m.weight) + nn.init.constant_(m.bias, 0.) + elif isinstance(m, nn.Conv2d): + torch.nn.init.xavier_uniform_(m.weight) + if m.bias is not None: + nn.init.constant_(m.bias, 0.) + elif isinstance(m, nn.BatchNorm2d): + nn.init.uniform_(m.weight, 0., 1.) + nn.init.constant_(m.bias, 0.) + + +class Leanable_Match_FilterV5(nn.Module): + def __init__(self, k_size, in_ch, out_ch, lmf_coef, activation='relu', bias=True): + super(Leanable_Match_FilterV5, self).__init__() + self.k_size = k_size + self.stride = 1 + self.in_ch = in_ch + self.out_ch = out_ch + self.activation = activation + self.bias = bias + self.lmf_real = nn.Conv2d(self.in_ch, self.out_ch, + kernel_size=(1, k_size), stride=(1, 1), + bias=self.bias) + self.lmf_imag = nn.Conv2d(self.in_ch, self.out_ch, + kernel_size=(1, k_size), stride=(1, 1), + bias=self.bias) + init.kaiming_uniform_(self.lmf_real.weight) + init.kaiming_uniform_(self.lmf_imag.weight) + if self.bias: + init.zeros_(self.lmf_real.bias) + init.zeros_(self.lmf_imag.bias) + self.cause_padding = torch.nn.ZeroPad2d(padding=(0, self.k_size - 1, 0, 0)) + self.cmplx_relu = ComplexReLU(self.activation) + + def forward(self, x): + inputR = self.cause_padding(x.real) + inputI = self.cause_padding(x.imag) + x_RR = self.lmf_real(inputR) + x_II = self.lmf_imag(inputI) + x_RI = self.lmf_imag(inputR) + x_IR = self.lmf_real(inputI) + x = x_RR - x_II + 1j * (x_RI + x_IR) + x = self.cmplx_relu(x) + return x + + +class LMF_Chain(nn.Module): + def __init__(self, configs): + super(LMF_Chain, self).__init__() + self.lmf_coef = filter_coef_loader(os.path.join(configs.dataset_path, configs.coef_path), configs.lmf_coefs) + self.in_ch = 1 + self.Chain = nn.Sequential() + for l in range(configs.lmf_layers): + self.Chain.add_module('lmfV5-{0}'.format(l), + Leanable_Match_FilterV5(k_size=self.lmf_coef.shape[1], + in_ch=self.in_ch, + out_ch=configs.lmf_channels, + lmf_coef=self.lmf_coef, + activation=configs.activation, + bias=configs.bias)) + self.in_ch = configs.lmf_channels + + def forward(self, x): + x = self.Chain(x) + return x + + +class Multi_Order_LDC(nn.Module): + def __init__(self, in_ch, out_ch, orders, activation='relu', bias=True): + super(Multi_Order_LDC, self).__init__() + self.in_ch = in_ch + self.out_ch = out_ch + self.orders = orders + self.activation = activation + self.bias = bias + self.ldc_list = nn.ModuleList() + self.pad_list = nn.ModuleList() + for n in range(self.orders): + ldc = nn.Conv2d(self.in_ch, self.out_ch, kernel_size=(n+2, 1), bias=self.bias) + pad = torch.nn.ZeroPad2d(padding=(0, 0, n+1, 0)) + self.in_ch = self.out_ch + self.ldc_list.append(ldc) + self.pad_list.append(pad) + self.cmplx_relu = ComplexReLU(self.activation) + self._initialize_MLDC_weights() + + def _initialize_MLDC_weights(self): + for n, conv in enumerate(self.ldc_list): + nn.init.kaiming_normal_(conv.weight) + if self.bias: + nn.init.zeros_(conv.bias) + + def forward(self, x): + B, P, R = x.shape[0], x.shape[2], x.shape[3] + x = x.unsqueeze(dim=1).broadcast_to(B, self.orders, x.shape[1], P, R) + y_r = torch.zeros(B, self.orders, self.out_ch, P, R).to(x.device) + y_i = torch.zeros(B, self.orders, self.out_ch, P, R).to(x.device) + for n in range(self.orders): + x_n_real = self.ldc_list[n](self.pad_list[n](x[:,n,...].real)) + x_n_imag = self.ldc_list[n](self.pad_list[n](x[:,n,...].imag)) + y_r[:,n,...] = x_n_real + y_i[:,n,...] = x_n_imag + y_r = y_r.view(B, self.orders*self.out_ch, P, R) + y_i = y_i.view(B, self.orders*self.out_ch, P, R) + y = torch.complex(y_r, y_i) + y = self.cmplx_relu(y) + return y + + +class Group_Purturble_DF(nn.Module): + def __init__(self, in_ch, out_ch, k_size, groups, activation='relu', bias=True): + super(Group_Purturble_DF, self).__init__() + self.k_size = k_size + self.in_ch = in_ch + self.out_ch = out_ch + self.groups = groups + self.activation = activation + self.bias = bias + self.gdf_cos = nn.Conv2d(self.in_ch*self.groups, self.out_ch*self.groups, + kernel_size=(k_size, 1), stride=(k_size, 1), + padding=0, groups=self.groups, bias=self.bias) + self.gdf_sin = nn.Conv2d(self.in_ch*self.groups, self.out_ch*self.groups, + kernel_size=(k_size, 1), stride=(k_size, 1), + padding=0, groups=self.groups, bias=self.bias) + self._initialize_GDF_weights() + self.cmplx_relu = ComplexReLU(self.activation) + + def _initialize_GDF_weights(self): + init.kaiming_uniform_(self.gdf_cos.weight) + init.kaiming_uniform_(self.gdf_sin.weight) + if self.bias: + init.zeros_(self.gdf_cos.bias) + init.zeros_(self.gdf_sin.bias) + + def forward(self, x): + B, R = x.shape[0], x.shape[3] + x_real, x_imag = x.real.to(x.device), x.imag.to(x.device) + x_rr = self.gdf_cos(x_real) + x_ii = self.gdf_sin(x_imag) + x_ri = self.gdf_sin(x_real) + x_ir = self.gdf_cos(x_imag) + x = x_rr + x_ii - 1j * x_ri + 1j * x_ir + x = self.cmplx_relu(x) + x = x.view(B, self.groups, self.out_ch, 1, R).squeeze(dim=3) + return x + + +class EchMo(nn.Module): + def __init__(self, configs): + super(EchMo, self).__init__() + self.cfg = configs + self.task_name = configs.task_name + self.n_range = configs.n_range + self.n_pulse = configs.n_pulse + self.n_classes = configs.n_classes + self.n_frames = configs.n_frames + self.scale = configs.scale + self.activation = configs.activation + self.bias = configs.bias + self.lmf_chains = configs.lmf_chains + self.lmf_channels = configs.lmf_channels + self.lmf_layers = configs.lmf_layers + self.lmf_coefs = configs.lmf_coefs + self.ldc_orders = configs.ldc_orders + self.ldc_channels = configs.ldc_channels + self.df_groups = configs.ldc_orders + self.df_channels = configs.df_channels + + self.LMFChain = nn.ModuleList([LMF_Chain(configs=self.cfg) for _ in range(self.lmf_chains)]) + self.MLDC = Multi_Order_LDC(in_ch=self.lmf_channels*self.lmf_chains, + out_ch=self.ldc_channels, + orders=self.ldc_orders, + activation=self.activation, + bias=self.bias) + self.GDF = Group_Purturble_DF(in_ch=self.ldc_channels, + out_ch=self.df_channels, + k_size=self.n_pulse, + groups=self.df_groups, + activation=self.activation, + bias=self.bias) + self.RDTranslator = PKCIn4ANY(n_classes=self.n_classes, + n_frames=self.n_frames, + in_ch=self.df_groups, + w=self.df_channels, + h=self.n_range) + self.RDTranslator.apply(_init_translator_weights) + + def forward(self, x): + if self.scale == 'instance': + x = complex_double2float(complex_std(x, epsilon=1e-8)) + elif self.scale == 'global': + x = complex_double2float(x) + + for i in range(self.lmf_chains): + if i == 0: + x_k = self.LMFChain[i](x) + else: + x_ki = self.LMFChain[i](x) + x_k = torch.concatenate([x_k, x_ki], dim=1) + x_h = self.MLDC(x_k) + x_d = self.GDF(x_h) + gdf_out = x_d + x_d = torch.abs(x_d).unsqueeze(dim=2) + y = self.RDTranslator(x_d) + return y, x_k, x_h, gdf_out diff --git a/models/fcn8s.py b/models/fcn8s.py new file mode 100644 index 0000000000000000000000000000000000000000..e6332ad344fd977b78455142f9116414b4e84613 --- /dev/null +++ b/models/fcn8s.py @@ -0,0 +1,289 @@ +# # from https://github.com/wkentaro/pytorch-fcn +import torch.nn as nn +from torch.nn import functional as F + +class FCN8s(nn.Module): + def __init__(self, n_classes=4, n_frames=5): + super(FCN8s, self).__init__() + # lt@20240406 reduce resolution + self.pool0 = nn.MaxPool2d(2, stride=2, ceil_mode=True) + + # conv1 + # The 100 pixel input padding guarantees that the network output can be aligned to the input for any input size + # since the kernel size of fc6 is 7 and its padding equals to 0. + self.conv1_1 = nn.Conv2d(n_frames, 64, 3, padding=100) + self.relu1_1 = nn.ReLU(inplace=True) + self.conv1_2 = nn.Conv2d(64, 64, 3, padding=1) + self.relu1_2 = nn.ReLU(inplace=True) + self.pool1 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/2 + + # conv2 + self.conv2_1 = nn.Conv2d(64, 128, 3, padding=1) + self.relu2_1 = nn.ReLU(inplace=True) + self.conv2_2 = nn.Conv2d(128, 128, 3, padding=1) + self.relu2_2 = nn.ReLU(inplace=True) + self.pool2 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/4 + + # conv3 + self.conv3_1 = nn.Conv2d(128, 256, 3, padding=1) + self.relu3_1 = nn.ReLU(inplace=True) + self.conv3_2 = nn.Conv2d(256, 256, 3, padding=1) + self.relu3_2 = nn.ReLU(inplace=True) + self.conv3_3 = nn.Conv2d(256, 256, 3, padding=1) + self.relu3_3 = nn.ReLU(inplace=True) + self.pool3 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/8 + + # conv4 + self.conv4_1 = nn.Conv2d(256, 512, 3, padding=1) + self.relu4_1 = nn.ReLU(inplace=True) + self.conv4_2 = nn.Conv2d(512, 512, 3, padding=1) + self.relu4_2 = nn.ReLU(inplace=True) + self.conv4_3 = nn.Conv2d(512, 512, 3, padding=1) + self.relu4_3 = nn.ReLU(inplace=True) + self.pool4 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/16 + + # conv5 + self.conv5_1 = nn.Conv2d(512, 512, 3, padding=1) + self.relu5_1 = nn.ReLU(inplace=True) + self.conv5_2 = nn.Conv2d(512, 512, 3, padding=1) + self.relu5_2 = nn.ReLU(inplace=True) + self.conv5_3 = nn.Conv2d(512, 512, 3, padding=1) + self.relu5_3 = nn.ReLU(inplace=True) + self.pool5 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/32 + + # fc6 + self.fc6 = nn.Conv2d(512, 4096, 7) + self.relu6 = nn.ReLU(inplace=True) + self.drop6 = nn.Dropout2d() + + # fc7 + self.fc7 = nn.Conv2d(4096, 4096, 1) + self.relu7 = nn.ReLU(inplace=True) + self.drop7 = nn.Dropout2d() + + self.score_fr = nn.Conv2d(4096, n_classes, 1) + self.score_pool3 = nn.Conv2d(256, n_classes, 1) + self.score_pool4 = nn.Conv2d(512, n_classes, 1) + + self.upscore2 = nn.ConvTranspose2d( + n_classes, n_classes, 4, stride=2, bias=False) + self.upscore8 = nn.ConvTranspose2d( + n_classes, n_classes, 16, stride=8, bias=False) + self.upscore_pool4 = nn.ConvTranspose2d( + n_classes, n_classes, 4, stride=2, bias=False) + + def forward(self, x): + # lt@20240406 reduce resolution + x = self.pool0(x) + # lt@20240408 add resolution + # x = F.interpolate(x, scale_factor=2, mode='bilinear', align_corners=True) + + h = x + h = self.relu1_1(self.conv1_1(h)) + h = self.relu1_2(self.conv1_2(h)) + h = self.pool1(h) + + h = self.relu2_1(self.conv2_1(h)) + h = self.relu2_2(self.conv2_2(h)) + h = self.pool2(h) + + h = self.relu3_1(self.conv3_1(h)) + h = self.relu3_2(self.conv3_2(h)) + h = self.relu3_3(self.conv3_3(h)) + h = self.pool3(h) + pool3 = h # 1/8 + + h = self.relu4_1(self.conv4_1(h)) + h = self.relu4_2(self.conv4_2(h)) + h = self.relu4_3(self.conv4_3(h)) + h = self.pool4(h) + pool4 = h # 1/16 + + h = self.relu5_1(self.conv5_1(h)) + h = self.relu5_2(self.conv5_2(h)) + h = self.relu5_3(self.conv5_3(h)) + h = self.pool5(h) + + h = self.relu6(self.fc6(h)) + h = self.drop6(h) + + h = self.relu7(self.fc7(h)) + h = self.drop7(h) + + h = self.score_fr(h) + h = self.upscore2(h) + upscore2 = h # 1/16 + + h = self.score_pool4(pool4) + # crop for alignment + h = h[:, :, 5:5 + upscore2.size()[2], 5:5 + upscore2.size()[3]] + score_pool4c = h # 1/16 + + h = upscore2 + score_pool4c # 1/16 + h = self.upscore_pool4(h) + upscore_pool4 = h # 1/8 + + h = self.score_pool3(pool3) + # crop + h = h[:, :, + 9:9 + upscore_pool4.size()[2], + 9:9 + upscore_pool4.size()[3]] + score_pool3c = h # 1/8 + + h = upscore_pool4 + score_pool3c # 1/8 + + h = self.upscore8(h) + # crop + h = h[:, :, 31:31 + x.size()[2], 31:31 + x.size()[3]].contiguous() + + # lt@20240406 recover resolution + h = F.interpolate(h, scale_factor=2, mode='bilinear', align_corners=True) + # lt@20240408 add resolution + # h = F.interpolate(h, scale_factor=0.5, mode='bilinear', align_corners=True) + return h + +# from https://github.com/wkentaro/pytorch-fcn +# import torch.nn as nn + +# class FCN8s(nn.Module): +# def __init__(self, n_classes=4, n_frames=5): +# super(FCN8s, self).__init__() +# # conv1 +# # The 100 pixel input padding guarantees that the network output can be aligned to the input for any input size +# # since the kernel size of fc6 is 7 and its padding equals to 0. +# self.conv1_1 = nn.Conv2d(n_frames, 64, 3, padding=100) +# self.bn1_1 = nn.BatchNorm2d(64) +# self.relu1_1 = nn.ReLU(inplace=True) +# self.conv1_2 = nn.Conv2d(64, 64, 3, padding=1) +# self.bn1_2 = nn.BatchNorm2d(64) +# self.relu1_2 = nn.ReLU(inplace=True) +# self.pool1 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/2 + +# # conv2 +# self.conv2_1 = nn.Conv2d(64, 128, 3, padding=1) +# self.bn2_1 = nn.BatchNorm2d(128) +# self.relu2_1 = nn.ReLU(inplace=True) +# self.conv2_2 = nn.Conv2d(128, 128, 3, padding=1) +# self.bn2_2 = nn.BatchNorm2d(128) +# self.relu2_2 = nn.ReLU(inplace=True) +# self.pool2 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/4 + +# # conv3 +# self.conv3_1 = nn.Conv2d(128, 256, 3, padding=1) +# self.bn3_1 = nn.BatchNorm2d(256) +# self.relu3_1 = nn.ReLU(inplace=True) +# self.conv3_2 = nn.Conv2d(256, 256, 3, padding=1) +# self.bn3_2 = nn.BatchNorm2d(256) +# self.relu3_2 = nn.ReLU(inplace=True) +# self.conv3_3 = nn.Conv2d(256, 256, 3, padding=1) +# self.bn3_3 = nn.BatchNorm2d(256) +# self.relu3_3 = nn.ReLU(inplace=True) +# self.pool3 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/8 + +# # conv4 +# self.conv4_1 = nn.Conv2d(256, 512, 3, padding=1) +# self.bn4_1 = nn.BatchNorm2d(512) +# self.relu4_1 = nn.ReLU(inplace=True) +# self.conv4_2 = nn.Conv2d(512, 512, 3, padding=1) +# self.bn4_2 = nn.BatchNorm2d(512) +# self.relu4_2 = nn.ReLU(inplace=True) +# self.conv4_3 = nn.Conv2d(512, 512, 3, padding=1) +# self.bn4_3 = nn.BatchNorm2d(512) +# self.relu4_3 = nn.ReLU(inplace=True) +# self.pool4 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/16 + +# # conv5 +# self.conv5_1 = nn.Conv2d(512, 512, 3, padding=1) +# self.bn5_1 = nn.BatchNorm2d(512) +# self.relu5_1 = nn.ReLU(inplace=True) +# self.conv5_2 = nn.Conv2d(512, 512, 3, padding=1) +# self.bn5_2 = nn.BatchNorm2d(512) +# self.relu5_2 = nn.ReLU(inplace=True) +# self.conv5_3 = nn.Conv2d(512, 512, 3, padding=1) +# self.bn5_3 = nn.BatchNorm2d(512) +# self.relu5_3 = nn.ReLU(inplace=True) +# self.pool5 = nn.MaxPool2d(2, stride=2, ceil_mode=True) # 1/32 + +# # fc6 +# self.fc6 = nn.Conv2d(512, 4096, 7) +# self.bn6 = nn.BatchNorm2d(4096) +# self.relu6 = nn.ReLU(inplace=True) +# self.drop6 = nn.Dropout2d() + +# # fc7 +# self.fc7 = nn.Conv2d(4096, 4096, 1) +# self.bn7 = nn.BatchNorm2d(4096) +# self.relu7 = nn.ReLU(inplace=True) +# self.drop7 = nn.Dropout2d() + +# self.score_fr = nn.Conv2d(4096, n_classes, 1) +# self.score_pool3 = nn.Conv2d(256, n_classes, 1) +# self.score_pool4 = nn.Conv2d(512, n_classes, 1) + +# self.upscore2 = nn.ConvTranspose2d( +# n_classes, n_classes, 4, stride=2, bias=False) +# self.upscore8 = nn.ConvTranspose2d( +# n_classes, n_classes, 16, stride=8, bias=False) +# self.upscore_pool4 = nn.ConvTranspose2d( +# n_classes, n_classes, 4, stride=2, bias=False) + +# def forward(self, x): +# h = x +# h = self.relu1_1(self.bn1_1(self.conv1_1(h))) +# h = self.relu1_2(self.bn1_2(self.conv1_2(h))) +# h = self.pool1(h) + +# h = self.relu2_1(self.bn2_1(self.conv2_1(h))) +# h = self.relu2_2(self.bn2_2(self.conv2_2(h))) +# h = self.pool2(h) + +# h = self.relu3_1(self.bn3_1(self.conv3_1(h))) +# h = self.relu3_2(self.bn3_2(self.conv3_2(h))) +# h = self.relu3_3(self.bn3_3(self.conv3_3(h))) +# h = self.pool3(h) +# pool3 = h # 1/8 + +# h = self.relu4_1(self.bn4_1(self.conv4_1(h))) +# h = self.relu4_2(self.bn4_2(self.conv4_2(h))) +# h = self.relu4_3(self.bn4_3(self.conv4_3(h))) +# h = self.pool4(h) +# pool4 = h # 1/16 + +# h = self.relu5_1(self.bn5_1(self.conv5_1(h))) +# h = self.relu5_2(self.bn5_2(self.conv5_2(h))) +# h = self.relu5_3(self.bn5_3(self.conv5_3(h))) +# h = self.pool5(h) + +# h = self.relu6(self.bn6(self.fc6(h))) +# h = self.drop6(h) + +# h = self.relu7(self.bn7(self.fc7(h))) +# h = self.drop7(h) + +# h = self.score_fr(h) +# h = self.upscore2(h) +# upscore2 = h # 1/16 + +# h = self.score_pool4(pool4) +# # crop for alignment +# h = h[:, :, 5:5 + upscore2.size()[2], 5:5 + upscore2.size()[3]] +# score_pool4c = h # 1/16 + +# h = upscore2 + score_pool4c # 1/16 +# h = self.upscore_pool4(h) +# upscore_pool4 = h # 1/8 + +# h = self.score_pool3(pool3) +# # crop +# h = h[:, :, +# 9:9 + upscore_pool4.size()[2], +# 9:9 + upscore_pool4.size()[3]] +# score_pool3c = h # 1/8 + +# h = upscore_pool4 + score_pool3c # 1/8 + +# h = self.upscore8(h) +# # crop +# h = h[:, :, 31:31 + x.size()[2], 31:31 + x.size()[3]].contiguous() + +# return h \ No newline at end of file diff --git a/models/tmva_net_sv.py b/models/tmva_net_sv.py new file mode 100644 index 0000000000000000000000000000000000000000..91d1d34eb670885c95980f3d00341cc62f6705be --- /dev/null +++ b/models/tmva_net_sv.py @@ -0,0 +1,422 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class DoubleConvBlock(nn.Module): + """ (2D conv => BN => LeakyReLU) * 2 """ + + def __init__(self, in_ch, out_ch, k_size, pad, dil): + super().__init__() + self.block = nn.Sequential( + nn.Conv2d(in_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm2d(out_ch), + nn.LeakyReLU(inplace=True), + nn.Conv2d(out_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm2d(out_ch), + nn.LeakyReLU(inplace=True) + ) + + def forward(self, x): + x = self.block(x) + return x + + +class Double3DConvBlock(nn.Module): + """ (3D conv => BN => LeakyReLU) * 2 """ + + def __init__(self, in_ch, out_ch, k_size, pad, dil): + super().__init__() + + self.block = nn.Sequential( + nn.Conv3d(in_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm3d(out_ch), + nn.LeakyReLU(inplace=True), + nn.Conv3d(out_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm3d(out_ch), + nn.LeakyReLU(inplace=True) + ) + + def forward(self, x): + x = self.block(x) + return x + + +class ConvBlock(nn.Module): + """ (2D conv => BN => LeakyReLU) """ + + def __init__(self, in_ch, out_ch, k_size, pad, dil): + super().__init__() + self.block = nn.Sequential( + nn.Conv2d(in_ch, out_ch, kernel_size=k_size, padding=pad, dilation=dil), + nn.BatchNorm2d(out_ch), + nn.LeakyReLU(inplace=True) + ) + + def forward(self, x): + x = self.block(x) + return x + +# reda peak_conv zlw @20220624 +# Peak Conv with fixed guard banwidth (gb) and dense reference receptive field (RRF) +class PeakConv2D(nn.Module): + def __init__(self, in_ch, out_ch, bias, refer_band, guard_band_dop, guard_band, signal_type): + """ + Args: + refer_band: a single integer value or integer vector of two values. + guard_band_dop: guard bandwidth for doppler input + guard_band: guard banwidth for non-doppler input + signal_type in ('range_doppler', 'angle_doppler', 'range_angle'). + k_size, padding and stride are computed using the input fixed guard bandwidth + input: x in the shape of BxCxHxW + """ + super(PeakConv2D, self).__init__() + self.signal_type = signal_type + if self.signal_type in ('range_doppler', 'angle_doppler'): + # guard_band should be bi-lateral + self.guard_band = (guard_band_dop, guard_band_dop) + # padding order: l-r-t-b + self.padding = (self.guard_band[1] + refer_band, + self.guard_band[1] + refer_band, + self.guard_band[0] + refer_band, + self.guard_band[0] + refer_band) + else: + self.guard_band = (guard_band, guard_band) + # padding order: l-r-t-b + self.padding = (self.guard_band[1] + refer_band, + self.guard_band[1] + refer_band, + self.guard_band[0] + refer_band, + self.guard_band[0] + refer_band) + self.refer_band = refer_band + self.kernel_size = (self.guard_band[0] + self.guard_band[1] + self.refer_band * 2), 4 + self.stride = self.kernel_size + # padding order: l-r-t-b + self.zero_padding = nn.ZeroPad2d(self.padding) + self.bias = bias + self.pc_strd = 1 + # conv block for peak receptive field (PRF) in x + # take PRF as input and output the center point output of PRF; + # kernel channel = in_ch*2: depth_concat(p_c, p_r) + # since each p_c is expanded as a tensor of kernel scale RF, the stride = kernel_size + self.peak_conv = nn.Conv2d(in_ch, out_ch, + kernel_size=self.kernel_size, + padding=0, + stride=self.stride, + bias=self.bias) + #self.peak_conv.register_backward_hook(self._set_lr) + + @staticmethod + # set learning rate for peak_conv + def _set_lr(module, grad_input, grad_output): + grad_input = (grad_input[i] * 0.1 for i in range(len(grad_input))) + grad_output = (grad_output[i] * 0.1 for i in range(len(grad_output))) + + def forward(self, x): + h, w = x.shape[2], x.shape[3] + rb = self.refer_band + gb = self.guard_band + k_pk = self.kernel_size + N = k_pk[0] * k_pk[1] + dtype = x.data.type() + b = x.size(0) + + x = self.zero_padding(x) + + # let p_r denote the reference point positions + # p_r shape: Bx2NxHxW + p_r = self._get_p_r(b, h, w, N, dtype) + # sample x_r (b, c, h, w, N) using p_r + x_r = self._sample_x(x, p_r, N) + # sample x_c (b, c, h, w, N) using p_c + p_c = self._get_p_c(b, h, w, N, dtype) + x_c = self._sample_x(x, p_c, N) + + # getting x_prf for peak_conv + # (b, c, h, w, N) ==> (b, 2c, h, w, N) + # x_prf = torch.cat((x_c, x_r), 1) + x_prf = x_c - x_r + # (b, 2c, h*k_pk[0], w*k_pk[1]) + x_prf = self._reshape_x_prf(k_pk[0], k_pk[1], x_prf) + + # out: (b, c, h, w) + out = self.peak_conv(x_prf) + return out + + # getting p_c (the center point coords) from the padded grid of input x + def _get_p_c(self, b, h, w, N, dtype): + # generating pc_grid + # for UserWarning in meshgrid, indexing='ij' @20240627 + p_c_x, p_c_y = torch.meshgrid( + torch.arange(self.padding[2], h * self.pc_strd + self.padding[2], self.pc_strd), + torch.arange(self.padding[0], w * self.pc_strd + self.padding[0], self.pc_strd), indexing='ij') + p_c_x = torch.flatten(p_c_x).view(1, 1, h, w).repeat(1, N, 1, 1) + p_c_y = torch.flatten(p_c_y).view(1, 1, h, w).repeat(1, N, 1, 1) + # p_c: 1x2NxHxW + p_c = torch.cat([p_c_x, p_c_y], 1).type(dtype) + # (B, 2N, h, w) + p_c = p_c.repeat(b, 1, 1, 1) + return p_c + + # generating peak receptive field grid + def _gen_prf_grid(self, rb, gb, N, dtype): + h_t = -(rb + gb[0]) + h_d = rb + gb[0] + w_l = -(rb + gb[1]) + w_r = rb + gb[1] + w_prf = (rb + gb[1]) * 2 + 1 + h_prf = (rb + gb[0]) * 2 + 1 + + prf_x_idx, prf_y_idx = torch.meshgrid( + torch.arange(h_t, h_d + 1), + torch.arange(w_l, w_r + 1), indexing='ij') + + # grid_size*2, 1 grid_size = (h_d*2+1) * (w_r*2+1) + # taking positions clockwise + prf_xt = prf_x_idx[0:rb] + prf_xr = prf_x_idx[rb:(h_prf - 2 * rb + 1), (w_prf - rb):w_prf] + prf_xd = prf_x_idx[(h_prf - rb):h_prf] + prf_xl = prf_x_idx[rb:(h_prf - 2 * rb + 1), 0:rb] + prf_x = torch.cat([torch.flatten(prf_xt), + torch.flatten(prf_xr), + torch.flatten(prf_xd), + torch.flatten(prf_xl)], 0) + prf_yt = prf_y_idx[0:rb] + prf_yr = prf_y_idx[rb:(h_prf - 2 * rb + 1), (w_prf - rb):w_prf] + prf_yd = prf_y_idx[(h_prf - rb):h_prf] + prf_yl = prf_y_idx[rb:(h_prf - 2 * rb + 1), 0:rb] + prf_y = torch.cat([torch.flatten(prf_yt), + torch.flatten(prf_yr), + torch.flatten(prf_yd), + torch.flatten(prf_yl)], 0) + + prf = torch.cat([prf_x, prf_y], 0) + prf = prf.view(1, 2 * N, 1, 1).type(dtype) + return prf + + # getting p_r positions from each p_c + def _get_p_r(self, b, h, w, N, dtype): + rb = self.refer_band + gb = self.guard_band + # (1, 2N, 1, 1) + prf = self._gen_prf_grid(rb, gb, N, dtype) + # (B, 2N, h, w) + p_c = self._get_p_c(b, h, w, N, dtype) + # (B, 2N, h, w) + p_r = p_c + prf + return p_r + + # sampling x using p_r or p_c + def _sample_x(self, x_pad, p, N): + p = p.contiguous().permute(0, 2, 3, 1).floor() + b, h, w, _ = p.size() + h_pad = x_pad.size(2) + w_pad = x_pad.size(3) + c = x_pad.size(1) + # (b, c, h_pad*w_pad) + # strech each spatial channel of x_pad as 1-D vector + x_pad = x_pad.contiguous().view(b, c, -1) + # (b, h_pad, w_pad, N) + # transform spatial coord of p into the 1-D index + index = p[..., :N] * w_pad + p[..., N:] + # index_x = torch.clamp(p[..., :N], 0, h_pad-1) + # index_y = torch.clamp(p[..., N:], 0, w_pad-1) + # index = index_x * w_pad + index_y + # (b, c, h*w*N) + index = index.contiguous().unsqueeze(dim=1).expand(-1, c, -1, -1, -1).contiguous().view(b, c, -1) + index = index.long().to(x_pad.device) + x_r = x_pad.gather(dim=-1, index=index).contiguous().view(b, c, h, w, N) + return x_r + + @staticmethod + # reshape the x_prf + def _reshape_x_prf(k_h, k_w, x_prf): + b, c, h, w, N = x_prf.size() + x_prf = torch.cat([x_prf[..., s:s + k_w].contiguous().view(b, c, h, w * k_w) for s in range(0, N, k_w)], dim=-1) + x_prf = x_prf.contiguous().view(b, c, h * k_h, w * k_w) + return x_prf + + +# double PeakConv2D block definition zlw @20220621 +class DoublePeakConv2D(nn.Module): + """ (2D PeakConv => BN => LeakyReLU) * 2 """ + + def __init__(self, in_ch, out_ch, bias, rb, gb_dop, gb, sig): + super(DoublePeakConv2D, self).__init__() + self.bias = bias + self.refer_band = rb + self.guard_band_dop = gb_dop + self.guard_band = gb + self.signal_type = sig + self.pk_conv1 = PeakConv2D(in_ch, out_ch, bias=self.bias, + refer_band=self.refer_band, + guard_band_dop=self.guard_band_dop, + guard_band=self.guard_band, + signal_type=self.signal_type) + self.bn1 = nn.BatchNorm2d(out_ch) + self.act1 = nn.LeakyReLU(inplace=True) + self.pk_conv2 = PeakConv2D(out_ch, out_ch, bias=self.bias, + refer_band=self.refer_band, + guard_band_dop=self.guard_band_dop, + guard_band=self.guard_band, + signal_type=self.signal_type) + self.bn2 = nn.BatchNorm2d(out_ch) + self.act2 = nn.LeakyReLU(inplace=True) + + def forward(self, x): + x = self.pk_conv1(x) + # print("x:", type(x)) + x = self.bn1(x) + x = self.act1(x) + x = self.pk_conv2(x) + x = self.bn2(x) + x = self.act2(x) + return x + + +class ASPPBlock(nn.Module): + """Atrous Spatial Pyramid Pooling + Parallel conv blocks with different dilation rate + """ + + def __init__(self, in_ch, out_ch, shape): + super().__init__() + self.shape = shape + self.global_avg_pool = nn.AvgPool2d(self.shape) + + self.conv1_1x1 = nn.Conv2d(in_ch, out_ch, kernel_size=1, padding=0, dilation=1) + self.single_conv_block1_1x1 = ConvBlock(in_ch, out_ch, k_size=1, pad=0, dil=1) + self.single_conv_block1_3x3 = ConvBlock(in_ch, out_ch, k_size=3, pad=6, dil=6) + self.single_conv_block2_3x3 = ConvBlock(in_ch, out_ch, k_size=3, pad=12, dil=12) + self.single_conv_block3_3x3 = ConvBlock(in_ch, out_ch, k_size=3, pad=18, dil=18) + + def forward(self, x): + x1 = F.interpolate(self.global_avg_pool(x), size=self.shape, align_corners=False, + mode='bilinear') + x1 = self.conv1_1x1(x1) + x2 = self.single_conv_block1_1x1(x) + x3 = self.single_conv_block1_3x3(x) + x4 = self.single_conv_block2_3x3(x) + x5 = self.single_conv_block3_3x3(x) + x_cat = torch.cat((x2, x3, x4, x5, x1), 1) + return x_cat + + +class EncodingBranch(nn.Module): + """ + Encoding branch for a single radar view + + PARAMETERS + ---------- + signal_type: str + Type of radar view. + Supported: 'range_doppler', 'range_angle' and 'angle_doppler' + """ + + def __init__(self, signal_type, n_frames, in_ch=1): + super().__init__() + self.signal_type = signal_type + self.n_frames = n_frames + self.in_ch = in_ch + self.double_3dconv_block1 = Double3DConvBlock(in_ch=self.in_ch, out_ch=32, + k_size=(1+n_frames//2, 3, 3), + pad=(0, 1, 1), dil=1) + self.doppler_max_pool = nn.MaxPool2d(2, stride=(1, 2)) + self.max_pool = nn.MaxPool2d(2, stride=2) + # self.double_conv_block2 = DoubleConvBlock(in_ch=128, out_ch=128, k_size=3, + # pad=1, dil=1) + self.double_conv_block2 = DoubleConvBlock(in_ch=32, out_ch=64, k_size=3, + pad=1, dil=1) + + # self.double_pkc_block = DoublePeakConv2D(in_ch=32, out_ch=64, + # bias=True, + # rb=1, + # gb_dop=1, + # gb=1, + # sig=self.signal_type) + self.single_conv_block1_1x1 = ConvBlock(in_ch=64, out_ch=128, k_size=1, + pad=0, dil=1) + + def forward(self, x): + x1 = self.double_3dconv_block1(x) + x1 = torch.squeeze(x1, 2) + + x1_pad = F.pad(x1, (0, 0, 0, 0), "constant", 0) + x1_down = self.max_pool(x1_pad) + + x2 = self.double_conv_block2(x1_down) + x2_pad = F.pad(x2, (0, 0, 0, 1), "constant", 0) + x2_down = self.doppler_max_pool(x2_pad) # + + x3 = self.single_conv_block1_1x1(x2_down) + # return input of ASPP block + latent features + return x2_down, x3 + + +class TMVANet_SV(nn.Module): + """ + Temporal Singel-View with ASPP Network (TMVA-Net) + + PARAMETERS + ---------- + n_classes: int + Number of classes used for the semantic segmentation task + n_frames: int + Total numer of frames used as a sequence + """ + + def __init__(self, n_classes, n_frames, in_ch, w, h): + super().__init__() + self.n_classes = n_classes + self.n_frames = n_frames + self.in_ch = in_ch + self.rd_shape = (int(w//2), int(h//4)) + + # Backbone (encoding) + self.rd_encoding_branch = EncodingBranch('range_doppler', self.n_frames, self.in_ch) + + # ASPP Blocks + self.rd_aspp_block = ASPPBlock(in_ch=64, out_ch=128, shape=self.rd_shape) + self.rd_single_conv_block1_1x1 = ConvBlock(in_ch=640, out_ch=128, k_size=1, pad=0, dil=1) + + # Decoding + # self.rd_single_conv_block2_1x1 = ConvBlock(in_ch=128, out_ch=128, k_size=1, pad=0, dil=1) + + # Pallel range-Doppler (RD) and range-angle (RA) decoding branches + self.rd_upconv1 = nn.ConvTranspose2d(256, 128, (2, 2), stride=(2, 2)) + self.rd_double_conv_block1 = DoubleConvBlock(in_ch=128, out_ch=128, k_size=3, + pad=1, dil=1) + self.rd_upconv2 = nn.ConvTranspose2d(128, 128, (1, 2), stride=(1, 2)) + self.rd_double_conv_block2 = DoubleConvBlock(in_ch=128, out_ch=128, k_size=3, + pad=1, dil=1) + + # Final 1D convs + self.rd_final = nn.Conv2d(in_channels=128, out_channels=n_classes, kernel_size=1) + + def forward(self, x_rd): + # Backbone + rd_features, rd_latent = self.rd_encoding_branch(x_rd) + + # ASPP blocks + x2_rd = self.rd_aspp_block(rd_features) + x2_rd = self.rd_single_conv_block1_1x1(x2_rd) + + # Latent Space + ASPP features + x4_rd = torch.cat((x2_rd, rd_latent), 1) + + # Parallel decoding branches with upconvs + x4_rd = self.rd_upconv1(x4_rd) + x4_rd = self.rd_double_conv_block1(x4_rd) + + x4_rd = self.rd_upconv2(x4_rd) + x4_rd = self.rd_double_conv_block2(x4_rd) + + # Final 1D convolutions + x4_rd = self.rd_final(x4_rd) + return x4_rd + + +if __name__ == '__main__': + data = torch.randn(8,1,1,128,1024) + model = TMVANet_SV(2,1,1,128,1024) + pre = model(data) + print(pre) \ No newline at end of file diff --git a/models/unet.py b/models/unet.py new file mode 100644 index 0000000000000000000000000000000000000000..799b784c533b051738325b4c000c6fd1b7d3a212 --- /dev/null +++ b/models/unet.py @@ -0,0 +1,275 @@ +# from https://github.com/milesial/Pytorch-UNet/tree/master +# This is a UNet model for CARRADA and KuRALS +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class DoubleConv(nn.Module): + """(convolution => [BN] => ReLU) * 2""" + + def __init__(self, in_channels, out_channels, mid_channels=None): + super().__init__() + if not mid_channels: + mid_channels = out_channels + self.double_conv = nn.Sequential( + nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False), + nn.BatchNorm2d(mid_channels), + nn.ReLU(inplace=True), + nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True) + ) + + def forward(self, x): + return self.double_conv(x) + + +class Down(nn.Module): + """Downscaling with maxpool then double conv""" + + def __init__(self, in_channels, out_channels): + super().__init__() + self.maxpool_conv = nn.Sequential( + nn.MaxPool2d(2), + DoubleConv(in_channels, out_channels) + ) + + def forward(self, x): + return self.maxpool_conv(x) + + +class Up(nn.Module): + """Upscaling then double conv""" + + def __init__(self, in_channels, out_channels, bilinear=True): + super().__init__() + + # if bilinear, use the normal convolutions to reduce the number of channels + if bilinear: + self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) + self.conv = DoubleConv(in_channels, out_channels, in_channels // 2) + else: + self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2) + self.conv = DoubleConv(in_channels, out_channels) + + def forward(self, x1, x2): + x1 = self.up(x1) + # input is BCHW + diffY = x2.size()[2] - x1.size()[2] + diffX = x2.size()[3] - x1.size()[3] + + x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2, + diffY // 2, diffY - diffY // 2]) + # if you have padding issues, see + # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a + # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd + x = torch.cat([x2, x1], dim=1) + return self.conv(x) + + +class OutConv(nn.Module): + def __init__(self, in_channels, out_channels): + super(OutConv, self).__init__() + self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1) + + def forward(self, x): + return self.conv(x) + +class UNet(nn.Module): + def __init__(self, n_classes, n_frames=5, bilinear=True): + """ + Args: + n_classes : _description_ + n_frames : _description_. Defaults to 5. + bilinear : Bilinear interpolation or ConvTranspose2d. + """ + super(UNet, self).__init__() + self.n_channels = n_frames + self.n_classes = n_classes + self.bilinear = bilinear + + # lt@20240406 reduce resolution + # self.pool0 = nn.MaxPool2d(2, stride=2, ceil_mode=True) + + self.inc = (DoubleConv(n_frames, 64)) + self.down1 = (Down(64, 128)) + self.down2 = (Down(128, 256)) + self.down3 = (Down(256, 512)) + factor = 2 if bilinear else 1 + self.down4 = (Down(512, 1024 // factor)) + self.up1 = (Up(1024, 512 // factor, bilinear)) + self.up2 = (Up(512, 256 // factor, bilinear)) + self.up3 = (Up(256, 128 // factor, bilinear)) + self.up4 = (Up(128, 64, bilinear)) + self.outc = (OutConv(64, n_classes)) + + def forward(self, x): + # lt@20240406 reduce resolution + # x = self.pool0(x) + # lt@20240408 add resolution + # x = F.interpolate(x, scale_factor=2, mode='bilinear', align_corners=True) + + x1 = self.inc(x) + x2 = self.down1(x1) + x3 = self.down2(x2) + x4 = self.down3(x3) + x5 = self.down4(x4) + x = self.up1(x5, x4) + x = self.up2(x, x3) + x = self.up3(x, x2) + x = self.up4(x, x1) + logits = self.outc(x) + + # lt@20240406 recover resolution + # logits = F.interpolate(logits, scale_factor=2, mode='bilinear', align_corners=True) + # lt@20240408 add resolution + # logits = F.interpolate(logits, scale_factor=0.5, mode='bilinear', align_corners=True) + + return logits + +# from https://github.com/milesial/Pytorch-UNet/tree/master +# import torch +# import torch.nn as nn +# import torch.nn.functional as F + +# lt@20240315 spatial group normalization +# lt@20240316 change fixed value 200 to w//4. +# class DoubleConv(nn.Module): +# """(convolution => [SGN] => ReLU) * 2""" + +# def __init__(self, in_channels, out_channels, mid_channels=None): +# super().__init__() +# if not mid_channels: +# mid_channels = out_channels +# self.conv1 = nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False) +# self.bn1_1 = nn.BatchNorm2d(mid_channels) +# self.bn1_2 = nn.BatchNorm2d(mid_channels) +# self.relu = nn.ReLU(inplace=True) + +# self.conv2 = nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False) +# self.bn2_1 = nn.BatchNorm2d(out_channels) +# self.bn2_2 = nn.BatchNorm2d(out_channels) + +# def forward(self, x): +# b, c, h, w = x.shape +# x = self.conv1(x) +# x11 = self.bn1_1(x[:, :, :, :(w//4)]) +# x12 = self.bn1_2(x[:, :, :, (w//4):]) +# x1 = self.relu(torch.concat([x11, x12], dim=-1)) + +# x2 = self.conv2(x1) +# x21 = self.bn2_1(x2[:, :, :, :(w//4)]) +# x22 = self.bn2_2(x2[:, :, :, (w//4):]) +# x2 = self.relu(torch.concat([x21, x22], dim=-1)) +# return x2 + +# lt@20240315 Group Normalization +# class DoubleConv(nn.Module): +# """(convolution => [GN] => ReLU) * 2""" + +# def __init__(self, in_channels, out_channels, mid_channels=None): +# super().__init__() +# if not mid_channels: +# mid_channels = out_channels +# self.double_conv = nn.Sequential( +# nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False), +# nn.GroupNorm(mid_channels//16, mid_channels), +# nn.ReLU(inplace=True), +# nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False), +# nn.GroupNorm(out_channels//16, out_channels), +# nn.ReLU(inplace=True) +# ) + +# def forward(self, x): +# return self.double_conv(x) + + +# class Down(nn.Module): +# """Downscaling with maxpool then double conv""" + +# def __init__(self, in_channels, out_channels): +# super().__init__() +# self.maxpool_conv = nn.Sequential( +# nn.MaxPool2d(2), +# DoubleConv(in_channels, out_channels) +# ) + +# def forward(self, x): +# return self.maxpool_conv(x) + + +# class Up(nn.Module): +# """Upscaling then double conv""" + +# def __init__(self, in_channels, out_channels, bilinear=True): +# super().__init__() + +# # if bilinear, use the normal convolutions to reduce the number of channels +# if bilinear: +# self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) +# self.conv = DoubleConv(in_channels, out_channels, in_channels // 2) +# else: +# self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2) +# self.conv = DoubleConv(in_channels, out_channels) + +# def forward(self, x1, x2): +# x1 = self.up(x1) +# # input is BCHW +# diffY = x2.size()[2] - x1.size()[2] +# diffX = x2.size()[3] - x1.size()[3] + +# x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2, +# diffY // 2, diffY - diffY // 2]) +# # if you have padding issues, see +# # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a +# # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd +# x = torch.cat([x2, x1], dim=1) +# return self.conv(x) + + +# class OutConv(nn.Module): +# def __init__(self, in_channels, out_channels): +# super(OutConv, self).__init__() +# self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1) + +# def forward(self, x): +# return self.conv(x) + +# class UNet(nn.Module): +# def __init__(self, n_classes, n_frames=5, bilinear=True): +# """ +# Args: +# n_classes : _description_ +# n_frames : _description_. Defaults to 5. +# bilinear : Bilinear interpolation or ConvTranspose2d. +# """ +# super(UNet, self).__init__() +# self.n_channels = n_frames +# self.n_classes = n_classes +# self.bilinear = bilinear + +# self.inc = (DoubleConv(n_frames, 64)) +# self.down1 = (Down(64, 128)) +# self.down2 = (Down(128, 256)) +# self.down3 = (Down(256, 512)) +# factor = 2 if bilinear else 1 +# self.down4 = (Down(512, 1024 // factor)) +# self.up1 = (Up(1024, 512 // factor, bilinear)) +# self.up2 = (Up(512, 256 // factor, bilinear)) +# self.up3 = (Up(256, 128 // factor, bilinear)) +# self.up4 = (Up(128, 64, bilinear)) +# self.outc = (OutConv(64, n_classes)) + +# def forward(self, x): +# x1 = self.inc(x) +# x2 = self.down1(x1) +# x3 = self.down2(x2) +# x4 = self.down3(x3) +# x5 = self.down4(x4) +# x = self.up1(x5, x4) +# x = self.up2(x, x3) +# x = self.up3(x, x2) +# x = self.up4(x, x1) +# logits = self.outc(x) +# return logits \ No newline at end of file diff --git a/models/vit.py b/models/vit.py new file mode 100644 index 0000000000000000000000000000000000000000..5488d34a31488b56344a029c9b95fea9a6f12b82 --- /dev/null +++ b/models/vit.py @@ -0,0 +1,165 @@ +import torch +from torch import nn +from torch.nn import Module, ModuleList + +from einops import rearrange, repeat +from einops.layers.torch import Rearrange + +# helpers + +def pair(t): + return t if isinstance(t, tuple) else (t, t) + +# classes + +class FeedForward(Module): + def __init__(self, dim, hidden_dim, dropout = 0.): + super().__init__() + self.net = nn.Sequential( + nn.LayerNorm(dim), + nn.Linear(dim, hidden_dim), + nn.GELU(), + nn.Dropout(dropout), + nn.Linear(hidden_dim, dim), + nn.Dropout(dropout) + ) + + def forward(self, x): + return self.net(x) + +class Attention(Module): + def __init__(self, dim, heads = 8, dim_head = 64, dropout = 0.): + super().__init__() + inner_dim = dim_head * heads + project_out = not (heads == 1 and dim_head == dim) + + self.heads = heads + self.scale = dim_head ** -0.5 + + self.norm = nn.LayerNorm(dim) + + self.attend = nn.Softmax(dim = -1) + self.dropout = nn.Dropout(dropout) + + self.to_qkv = nn.Linear(dim, inner_dim * 3, bias = False) + + self.to_out = nn.Sequential( + nn.Linear(inner_dim, dim), + nn.Dropout(dropout) + ) if project_out else nn.Identity() + + def forward(self, x): + x = self.norm(x) + + qkv = self.to_qkv(x).chunk(3, dim = -1) + q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.heads), qkv) + + dots = torch.matmul(q, k.transpose(-1, -2)) * self.scale + + attn = self.attend(dots) + attn = self.dropout(attn) + + out = torch.matmul(attn, v) + out = rearrange(out, 'b h n d -> b n (h d)') + return self.to_out(out) + +class Transformer(Module): + def __init__(self, dim, depth, heads, dim_head, mlp_dim, dropout = 0.): + super().__init__() + self.norm = nn.LayerNorm(dim) + self.layers = ModuleList([]) + + for _ in range(depth): + self.layers.append(ModuleList([ + Attention(dim, heads = heads, dim_head = dim_head, dropout = dropout), + FeedForward(dim, mlp_dim, dropout = dropout) + ])) + + def forward(self, x): + for attn, ff in self.layers: + x = attn(x) + x + x = ff(x) + x + + return self.norm(x) + +class ViT(Module): + def __init__(self, img_size=(128, 1024), patch_size=16, in_chans=2, n_classes=2, embed_dim=128, depth=6, num_heads=8, mlp_ratio=4., emb_dropout=0.2, dropout=0.2): + super().__init__() + image_height, image_width = pair(img_size) + patch_height, patch_width = pair(patch_size) + self.n_classes = n_classes + + assert image_height % patch_height == 0 and image_width % patch_width == 0, 'Image dimensions must be divisible by the patch size.' + + self.grid_h = image_height // patch_height # 128//16=8 + self.grid_w = image_width // patch_width # 1024//16=64 + + num_patches = self.grid_h * self.grid_w + patch_dim = in_chans * patch_height * patch_width + + self.to_patch_embedding = nn.Sequential( + Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = patch_height, p2 = patch_width), + nn.LayerNorm(patch_dim), + nn.Linear(patch_dim, embed_dim), + nn.LayerNorm(embed_dim), + ) + + self.cls_token = nn.Parameter(torch.randn(1, 1, embed_dim)) # num_cls_tokens = 1 + self.pos_embedding = nn.Parameter(torch.randn(1, num_patches + 1, embed_dim)) + + self.dropout = nn.Dropout(emb_dropout) + + dim_head = embed_dim // num_heads + mlp_dim = int(embed_dim * mlp_ratio) + self.transformer = Transformer(embed_dim, depth, num_heads, dim_head, mlp_dim, dropout) + + self.seg_head = nn.Sequential( + Rearrange('b (h w) d -> b d h w', h=8, w=64, d=128), + # 8×64 → 16×128 + nn.Upsample(scale_factor=(2,2), mode='bilinear', align_corners=False), + nn.Conv2d(128, 64, 3, padding=1, bias=False), + nn.BatchNorm2d(64), + nn.GELU(), + # 16×128 → 32×256 + nn.Upsample(scale_factor=(2,2), mode='bilinear', align_corners=False), + nn.Conv2d(64, 32, 3, padding=1, bias=False), + nn.BatchNorm2d(32), + nn.GELU(), + # 32×256 → 128×1024( + nn.Upsample(scale_factor=(4,4), mode='bilinear', align_corners=False), + nn.Conv2d(32, self.n_classes, 1, padding=0), + ) + + + + def forward(self, img): + batch = img.shape[0] + x = self.to_patch_embedding(img) + + cls_tokens = repeat(self.cls_token, '1 1 d -> b 1 d', b=batch) + x = torch.cat((cls_tokens, x), dim = 1) + + seq = x.shape[1] + + x = x + self.pos_embedding[:, :seq, :] + x = self.dropout(x) + + x = self.transformer(x) + + # # classification task + # x = x[:, 0] + # x = self.to_latent(x) + # x = self.mlp_head(x) + + # segmentation task + x = x[:, 1:, :] # drop CLS, shape (batch, num_patches, embed_dim) + x = self.seg_head(x) + + return x + +if __name__ == "__main__": + model = ViT() + input_img = torch.randn(2, 2, 128, 1024) + print("input shape:", input_img.shape) # output: torch.Size([2, 2, 128, 1024]) + output = model(input_img) + print("output shape:", output.shape) # output: torch.Size([2, 2, 128, 1024]) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..990e180a170dfdf342ab90a810c10bf60c9d01e6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,21 @@ +# Deep Learning Framework +# PyPI ships the CUDA-enabled build. On a CPU-only machine you can save ~2.5 GB: +# pip install torch --index-url https://download.pytorch.org/whl/cpu +# (run that first, then pip install -r requirements.txt) +torch>=2.0.0 + +# Web Interface +gradio==6.9.0 # pinned for reproducible builds (uses gr.Timer, launch(theme=, css=, head=)) + +# Scientific Computing +numpy>=1.24.0 +scipy>=1.10.0 +pandas>=2.0.0 # imported directly by app.py + +# Visualization +matplotlib>=3.7.0 +plotly>=5.15.0 +Pillow>=10.0.0 + +# Model backbones +einops>=0.7.0 # required by models/vit.py