Adaptive Sensing
#What this repository does
adaptive-sensing is a research and prototype system for adaptive electronic-warfare spectrum surveillance.
Its purpose is to control a receiver that cannot listen to the entire radio-frequency spectrum at once. The receiver has a fixed set of frequency channels and can observe only one channel during each short time window, called a dwell. The system must decide:
- Which channel should be scanned next?
- Should it follow the normal sequential sweep?
- Is it worth temporarily diverting to another channel?
- Will that diversion help discover an unknown or intermittent emitter?
- Will the diversion leave another channel unobserved for too long?
The project simulates this problem using synthetic radar/emitter data, evaluates multiple scheduling strategies, trains predictive models, and presents the results through a tactical web dashboard.
The central idea is:
Instead of repeatedly listening to the loudest channel, choose the next scan based on the expected long-term mission value of discovering previously unseen emitters while still maintaining safe coverage of the whole spectrum.
The repository calls this system Q-Scheduler.
#Overall architecture
The main data flow is:
Radar/emitter dataset
|
v
Dataset loading and PDW parsing
|
v
RF/time-frequency environment
|
v
Simulated receiver observations
|
v
Historical and causal feature extraction
|
v
Activity and mission-value prediction
|
v
Candidate scan actions
|
v
Scheduler/planner chooses next channel
|
v
Safety gate approves or vetoes the action
|
v
Receiver observes the selected channel
|
+----> Evaluation metrics and benchmark reports
|
+----> Frontend dashboard and comparison visualizations
The system has four broad layers:
| Layer | Location | Purpose |
|---|---|---|
| Research and simulation backend | backend/src/ | Receiver simulation, features, schedulers, evaluation |
| Advanced Q-Scheduler backend | backend/q_scheduler/ | Predictive models and mission-level planning |
| API layer | backend/api/server.py | Exposes comparisons and live streams to the dashboard |
| Operator dashboard | frontend/ew-dashboard/ | Visualizes spectrum activity, scan decisions, threats, and policy comparisons |
The repository also contains a large body of documentation and experimental artifacts under docs/ and reports/.
#The electronic-warfare problem being solved
The project models a receiver with approximately 36 frequency channels:
- Some channels require a longer dwell, such as 100 ms.
- Other channels require a shorter dwell, such as 50 ms.
- A complete nominal sequential sweep takes about 2.15 seconds.
A simple receiver would scan channel 0, then channel 1, then channel 2, and so on. This guarantees coverage, but it may miss a short-lived emitter that transmits while the receiver is listening elsewhere.
A naïve adaptive scheduler has the opposite problem: it may discover many pulses on one busy channel and keep returning there, starving the rest of the spectrum.
This project therefore tries to balance:
- Exploration — visiting channels that may contain undiscovered threats.
- Exploitation — returning to channels where useful activity is predicted.
- Coverage — ensuring no channel remains unobserved for too long.
- Causal decision-making — only using information available up to the current time.
- Mission-level value — optimizing early emitter discovery rather than just immediate pulse count.
The main objective is cumulative undiscovered-emitter time, represented in the documentation as J. Lower J means emitters were discovered earlier.
#Top-level directories and files
This is the primary project explanation. It covers:
- The EW problem
- Terminology such as PDW, PRI, dwell, raster, and partial observability
- The Q-Scheduler design
- The Discovery-Aware and Opportunity-Cost planners
- The safety-coverage rule
- Benchmark results
- Reproducibility commands
- The intended directory structure
It is written partly for technical evaluators and partly for Smart India Hackathon judges.
This is the system’s formal architecture specification. It defines:
- The dataset assumptions
- What information the scheduler may and may not use
- The receiver and observation model
- Frequency and time representations
- Feature and belief-state concepts
- Scheduler interfaces
- Reinforcement-learning formulation
- Evaluation metrics
- Experimental scenarios
- Development phases and success criteria
This file describes the intended architecture at a conceptual level, including some structures that have since evolved in the implementation.
Contains repository-level GitHub configuration, likely including workflows, issue or contribution settings, and automation metadata.
Contains detailed technical specifications and phase-by-phase validation reports. Important documents include:
DATASET_ARCHITECTURE.md— dataset structure and data assumptionsOBSERVABILITY_RULES.md— rules preventing the scheduler from using future or hidden informationPHASE1_VALIDATION.md— initial dataset validationPHASE2_RF_ENVIRONMENT.md— RF environment and receiver simulationPHASE3_BASELINES.md— baseline scheduler definitionsPHASE4_FEATURE_ENGINEERING.md— engineered state featuresPHASE5_2_ML_MODELS.md— predictive ML modelsPHASE6_REINFORCEMENT_LEARNING.md— RL-related workPHASE7.mdand related files — later planning, predictive, and causal-state workCOUNTERFACTUAL_ENVIRONMENT_AUDIT.md— checks around counterfactual evaluationPOST_RESTRUCTURE_VALIDATION.md— validation after repository restructuring
These documents function as the project’s research notebook and audit trail.
Contains generated experiment outputs rather than core source code. There are many CSV, JSON, Markdown, PNG, and NumPy artifacts covering:
- Benchmark summaries
- Per-scenario metrics
- Bootstrap confidence intervals
- Calibration curves
- Feature importance
- Ablation studies
- Leakage audits
- Reproducibility runs
- Reinforcement-learning experiments
- Decision traces
- Root-cause diagnostics
- Phase 6 and Phase 7 validation
The reports directory is useful for verifying research claims and comparing policies, but it is not generally needed to understand the runtime architecture.
The repository-level scripts currently focus on later validation and experiment execution, including:
run_phase6_3_candidate_a_validation.pyrun_phase6_3_candidate_b_validation.pyrun_phase6_3_single_scenario.py
These scripts execute specific research experiments and generate trace or validation artifacts.
#Backend
The backend is Python-based. Its dependencies include NumPy, SciPy, h5py, Matplotlib, FastAPI, Uvicorn, and pytest.
This package is responsible for bringing raw scenario data into the system.
#dataset_loader.py
Defines structures such as:
RawPDWTableScenarioDataDatasetLoader
It loads and represents pulse data and scenario-level metadata.
#scan_parser.py
Defines receiver and transmitter metadata:
ChannelConfigReceiverConfigTransmitterMetadata
It parses the hardware configuration of the receiver and the metadata describing simulated emitters.
#preprocessing.py
Provides data validation and time-unit conversion helpers, including conversion between microseconds and seconds.
#hardware_constants.py
Contains receiver-specific timing and channel rules, such as canonical dwell durations and wideband-channel identification.
This package simulates the physical RF world and the receiver’s limited view of it.
#rf_environment.py
Represents the RF environment containing channels, emitters, pulses, and activity over time.
#receiver.py
Implements the receiver simulator. It models what the receiver actually observes after selecting a channel and dwell duration.
#actions.py
Defines the scan action taken by the receiver, such as selecting a channel and observing it for a specific dwell.
#observations.py
Defines the observation returned after a dwell. This is the information available to the scheduler, rather than the full hidden ground truth.
#time_frequency_grid.py
Represents activity on a two-dimensional time/frequency grid.
#phase7_environment.py
Provides a later-stage environment for the Phase 7 planning and learning experiments.
#rl_environment.py
Contains reinforcement-learning environment abstractions such as discrete, box, and dictionary spaces.
#synthetic_world.py
Creates small synthetic scenarios for development and testing. It includes helpers for generating four-channel receivers and synthetic pulse streams.
#reward.py
Defines reward configuration and reward breakdown calculations for learning-based schedulers.
#potential.py
Implements potential-based state shaping, especially around channel staleness.
#lagrangian.py
Provides constraint-pressure and dual-variable logic for constrained scheduling experiments.
This package converts receiver history into scheduler features.
#extractor.py
The main feature-extraction layer. It produces structured spectrum feature state from the receiver’s observation history.
#types.py
Defines the feature data structures:
FeatureConfigActivityFeaturesStalenessFeaturesTemporalFeaturesSpectralFeaturesSpatialFeaturesCrossBandFeaturesBandFeatures
#Activity and history trackers
activity.py— tracks recent activity by bandstaleness.py— tracks how long each channel has gone without observationtemporal.py— extracts temporal pulse behaviorspectral.py— extracts frequency and spectral behaviorspatial.py— tracks angle-of-arrival informationcross_band.py— captures relationships between channelscausal_temporal.py— tracks temporal state without using future datacompact_state.py— turns the state into compact vector representations
Together, these modules provide the information needed for a scheduler to make an informed decision without seeing the hidden future.
This contains the general predictive-model framework.
#predictor_service.py
Provides a service layer for loading and querying predictive models.
#models/activity/
This package contains activity-prediction models:
base.py— abstract predictor interfacehistorical_rate.py— predicts based on historical activity ratepersistence.py— predicts that recent activity will continuelogistic.py— logistic-regression-based predictorgradient_boosting.py— gradient-boosting predictordataset.py— builds model-training datasetstargets.py— creates prediction targetssplits.py— controls scenario-level data splitsevaluator.py— evaluates prediction qualitypipeline.py— training, prediction, calibration, and reproducibility pipelineconfig.py— model and pipeline configuration
The package supports both simple baselines and more sophisticated learned predictors.
This contains the scheduler implementations that choose the next scan action.
#Common interface
base.py— abstractBaseScheduleractions.py— converts between channel actions and adaptive action representationscandidate.py— generates candidate channels and opportunitiespolicies.py— reusable candidate-selection policiesaction_value.py— computes action values and feasibility
#Baseline schedulers
random.py— random channel selectionsequential.py— fixed cyclic sweepgreedy.py— immediate activity or recency-based selectionucb.py— upper-confidence-bound explorationthompson.py— Thompson samplingwhittle.py— Whittle-index-style schedulingoracle.py— clairvoyant reference scheduler using privileged informationhierarchical.py— hierarchical schedulingdqn_scheduler.py— deep Q-network-based scheduler
#More advanced schedulers
smartscan.py— adaptive scoring based on sensing valuetemporal_predictor_scheduler.py— uses temporal activity predictionshort_horizon_planner.py— short-term planning baselineresidual.py— residual policy and safety gate logicvalue.py— opportunity-value and SmartScan scoringdqn.py— neural Q-network, replay buffer, and DDQN implementationprioritized_replay.py— staleness-stratified prioritized replay
This package contains both simple reference policies and more experimental learned or value-based schedulers.
This package determines whether a scheduler is actually useful.
#counterfactual_replay.py
Replays scenarios and evaluates what would have happened if a different action had been selected. It includes:
- Scenario loading
- Dwell observation
- Sequential baseline replay
- Counterfactual decision evaluation
- Mission-objective calculation
- Continuation rollout
#metrics.py
Computes performance measures such as:
- Coverage
- Discovery success
- Interception ratio
- Discovery latency
- Revisit gaps
- Starvation gaps
- Short-burst capture
- Bootstrap confidence intervals
#ground_truth.py
Compares scan histories against the complete hidden scenario ground truth.
#engine.py and runner.py
Provide general experiment execution and result collection.
#benchmark_harness.py
Runs canonical benchmark experiments, builds schedulers, evaluates scenarios, and computes aggregate statistics.
Contains the general backend test suite. The repository currently contains approximately 68 test files in this area.
These tests enforce:
- Receiver behavior
- Partial observability
- Feature correctness
- Scheduler decisions
- Evaluation metrics
- Information-leakage restrictions
- Environment invariants
Contains exploratory research notebooks:
phase2_environment_demo.ipynbphase4_feature_exploration.ipynb
These are useful for understanding the project interactively rather than through production-style modules.
Contains compressed train, validation, and test CSV datasets for temporal modeling.
#The backend/q_scheduler/ subsystem
This is the most specialized part of the backend. It implements the mission-level Q-Scheduler rather than only the generic scheduler framework.
Its main decision is between:
- KEEP — continue the nominal raster sweep.
- OVERRIDE — temporarily scan a different channel because the predicted mission benefit justifies the diversion.
Contains configuration definitions for different research phases:
phase4b2_config.pyphase5_config.pyphase6_config.pypilot_config.pyq_h_v2_config.py
These define feature schemas, cohort sizes, evaluation parameters, thresholds, and model paths.
Contains training and evaluation dataset construction tools:
- Dataset generators
- Counterfactual replay extractors
- Dataset manifests
- Pydantic row schemas
- Scenario partition metadata
- Replacement and deferred-training utilities
This package creates supervised examples from simulated decisions and counterfactual outcomes.
Contains the mission-level predictive models.
#q_h_bundle.py
Loads frozen multi-horizon Q_H regressors. These estimate the expected improvement or degradation in mission objective from taking a candidate action.
The repository includes several time horizons, such as:
- 50 ms
- 100 ms
- 250 ms
- 500 ms
- 1 second
- 2.15 seconds
- Full mission horizon
#mission_risk_bundle.py
Loads the mission-risk model. This predicts the probability that an override will produce a positive mission outcome.
#Training modules
train_qh.pytrain_mission_risk.pymission_risk_factory.pyq_h_v2_training_preparation.py
These prepare and train the predictive models.
#Model artifacts
models/q_h/contains frozen Q-H model files and metadata.models/mission_risk/contains the mission-risk model and its feature schema.models/q_h_v2/contains schema and metadata for the newer model version.
This is the central planning package.
#decision_planner.py
The main planner that routes candidate actions through the available policy logic.
#discovery_gate.py
Implements anti-repetition behavior. Once a channel has produced a useful discovery, the scheduler should not repeatedly return there simply because it remains active.
#opportunity_cost.py
Calculates the cost of diverting from the normal raster. It considers whether:
- The current raster channel is becoming stale.
- The candidate channel will naturally be visited soon anyway.
- The override creates unnecessary displacement.
- The candidate provides enough expected mission gain.
#dynamic_keep.py
Calculates a dynamic threshold for deciding whether an override is valuable enough to beat the KEEP action.
#contextual_gate.py
Allows a previously suppressed channel to become eligible again when new temporal or burst evidence appears.
#safety_feasibility.py
Performs safety prechecks on candidate actions.
#planner_types.py
Defines the planner’s core data structures, including candidates, policies, configurations, and inference results.
Contains CausalTemporalEpisodeTracker and related channel episode tracking logic.
It maintains state such as:
- Recent observations
- Channel visit history
- Last scan times
- Active burst episodes
- Emitter-related temporal evidence
It is designed to ensure that planning decisions only use information available at the current point in time.
Analyzes periodic emitter behavior.
periodic_analyzer.py— PRI autocorrelation and harmonic analysisperiodic_types.py— result data structuressynthetic_benchmarks.py— synthetic periodic-signal generationreal_data_smoke_test.py— smoke tests against real scenario filesadversarial_audit.py— stress tests for periodic analysis
This supports detection of radar pulse trains and intelligent re-entry into channels with periodic activity.
Contains specialized evaluation tools:
baseline_evaluator.py— evaluates the sequential sweepcanonical_four_way_evaluation.py— compares several scheduler familiesplanner_ablation.py— runs model and policy ablationscounterfactual.py— constructs counterfactual targetsmission_risk_evaluator.py— evaluates risk predictionqh_evaluator.py— validates Q-H modelsprotected_data_guard.py— prevents accidental use of protected holdout dataaction_space_audit.py— checks candidate-action parityq_h_v2_leakage_audit.py— searches for feature leakage
Contains approximately 32 focused tests for the advanced planner subsystem, including:
- Opportunity-cost behavior
- Discovery-gate cooldowns
- Dynamic KEEP thresholds
- Planner routing
- Determinism
- Causal state behavior
- Safety and fallback behavior
#API layer
This is the FastAPI entry point for the dashboard-facing backend.
It exposes:
| Endpoint | Purpose |
|---|---|
GET / | Basic API/root response |
GET /api/training_curves | Returns training-curve data |
GET /api/policies | Lists available comparison policies |
GET /api/configs | Lists available STARE scenario configurations |
GET /api/comparison/{config_id} | Runs a complete sequential-versus-adaptive comparison |
GET /api/stream/{config_id} | Streams comparison steps using Server-Sent Events |
The available policies are:
da— Discovery-Awareopp_cost— Opportunity-Costdynamic_keep— Dynamic KEEPshp— Short-Horizon Planner
The server:
- Loads STARE scenario data.
- Parses receiver and emitter information.
- Builds a frequency/time heatmap.
- Simulates a sequential baseline.
- Simulates the selected adaptive policy.
- Tracks emitter discovery and mission objective values.
- Returns comparison steps, divergences, emitter data, and summary metrics.
It also maintains in-memory caches for scenario data, heatmaps, emitter metadata, preprocessing results, and comparison results.
The API expects scenario data in external runtime locations such as:
stare/
scan/
Those directories are not present in the attached repository, so a fresh checkout will need the corresponding scenario data before the API can run successfully.
#Frontend dashboard
The frontend is a Next.js application located at:
frontend/ew-dashboard/
It uses:
- React
- Next.js
- TypeScript
- Recharts
- Framer Motion
- Lucide icons
- Tailwind CSS
#src/app/page.tsx
The main dashboard page.
It provides:
- Scenario selection
- Scan playback controls
- Spectrum waterfall visualization
- Emitter inspection
- Decision log
- Dataset explorer
- Frequency, amplitude, PRF, AoA, and interception charts
- Training curves
- Sidebar and status bar controls
The page loads pre-generated JSON from paths such as:
/data/config_list.json
/data/test_stats.json
/data/config_0.json
#src/app/compare/page.tsx
A thin route wrapper that displays ComparisonPage.
#src/app/radar/page.tsx
A more focused radar-style view containing:
- Radar scope
- Mission scoreboard
- Threat-band list
- Radar event feed
- Mission timeline
- Playback controls
#src/app/layout.tsx
Defines global layout, metadata, viewport settings, and application-level wrappers.
#src/app/globals.css
Contains the dashboard’s global styling and visual theme.
#src/app/loading.tsx
Displays the loading UI while a page is being prepared.
#src/app/error.tsx
Provides the route-level error boundary.
#Frontend components
SpectrumWaterfall.tsx— time/frequency waterfall displayFrequencySpectrum.tsx— frequency distribution chartAmplitudeDistribution.tsx— pulse-amplitude distributionPRFHistogram.tsx— pulse-repetition-frequency visualizationAoAPolarPlot.tsx— angle-of-arrival plotScatterPlot.tsx— pulse feature scatter plotBandEmitterHeatmap.tsx— emitter activity by bandEmitterFeatureSpace.tsx— emitter feature-space visualizationInterceptionRatioOverTime.tsx— interception performance over timeCumulativeDetectionCurve.tsx— cumulative discovery behaviorTrainingCurves.tsx— ML training and validation curvesScanTimeline.tsx— scan progression over the missionDecisionLog.tsx— chronological scheduler decisionsDatasetExplorer.tsx— scenario-level dataset statisticsEmitterDetailPanel.tsx— details for the selected emitterSidebar.tsx— channel/scenario navigationStatusBar.tsx— system status and mission indicatorsLoadingSkeleton.tsx— loading placeholders
The src/components/compare/ directory is dedicated to policy comparison:
ComparisonPage.tsx— orchestrates the comparison screenComparisonTopBar.tsx— policy and scenario controlsComparisonMetrics.tsx— comparison metricsComparisonRadarScope.tsx— visual radar comparisonComparisonWaterfall.tsx— sequential versus adaptive waterfallComparisonTimeline.tsx— side-by-side scan timelineComparisonThreatMatrix.tsx— threat-discovery comparisonComparisonDivergenceBanner.tsx— highlights policy divergenceDivergenceLog.tsx— records moments where the policies choose differentlyemitterColors.ts— consistent emitter coloring utilities
The src/components/radar/ directory provides the more tactical operator view:
RadarScope.tsxMissionScoreboard.tsxThreatBandList.tsxRadarEventFeed.tsxMissionTimeline.tsx
#Frontend hooks and types
Central playback state for moving through mission time.
It manages:
- Current scan step
- Play and pause
- Forward and backward stepping
- Playback speed
- Reset
- Progress calculation
Animates numeric dashboard values.
Provides animation-frame utilities, interpolation, and clamping.
Defines the structure of scenario JSON data and test-stat records.
Defines policy identifiers and comparison types. It includes the four supported policy IDs and helper functions for displaying policy names.
#Frontend data-generation scripts
Reads HDF5 scan files and converts them into dashboard-friendly JSON.
It extracts information such as:
- Pulse descriptors
- Emitter types
- Frequency data
- Time-of-arrival values
- Pulse widths
- AoA
- Amplitude
- PRF information
- Band statistics
- Downsampled scatter data
The generated files are written to:
frontend/ew-dashboard/public/data/
Converts dataset-level CSV statistics into test_stats.json for the dashboard.
The scripts expect a repository-level scan/ directory. In the attached copy, that directory is not present, and the generated public/data/ files are also not present. Therefore, the frontend source exists, but the default dashboard data must be generated or supplied before it can operate as intended.
#How the key scheduling policies differ
The fixed baseline. It visits channels in order and provides predictable coverage.
Its strength is reliability and coverage. Its weakness is that it cannot react to short-lived opportunities.
Chooses a channel based mainly on immediate pulse or discovery opportunity. It is useful as a legacy or myopic baseline, but it can over-focus on currently active channels.
Prioritizes channels containing emitters that have not yet been discovered. It also uses an anti-repetition memory to avoid repeatedly scanning an already-understood channel.
Improves on Discovery-Aware behavior by charging an explicit cost for leaving the nominal raster. It asks:
- Is the candidate channel about to be visited naturally?
- Is the raster channel becoming stale?
- Is the predicted gain large enough to justify the diversion?
- Will this override cause unnecessary displacement?
Computes a dynamic hurdle for overriding the raster. The scheduler remains with the nominal scan unless the best candidate exceeds the current KEEP threshold.
#The safety mechanism
The system does not allow an adaptive policy to divert indefinitely.
The safety gate projects future channel revisit times and vetoes an override if it would cause a channel to remain unvisited beyond the allowed starvation limit. The documentation describes this limit as approximately 2.30 seconds, slightly longer than the nominal 2.15-second sweep to provide limited maneuvering slack.
When an override is rejected, the system falls back to the scheduled raster action.
This is important because the adaptive policy is not allowed to sacrifice broad spectrum surveillance merely to chase a locally attractive signal.
#What is production/runtime code versus research material?
The most operationally relevant files are:
backend/api/server.py
backend/src/data/
backend/src/environment/
backend/src/features/
backend/src/schedulers/
backend/src/evaluation/
backend/q_scheduler/planner/
backend/q_scheduler/models/
backend/q_scheduler/state/
frontend/ew-dashboard/src/
These areas are primarily for experimentation, validation, and scientific analysis:
backend/notebooks/
backend/q_scheduler/evaluation/
backend/q_scheduler/scripts/
scripts/
reports/
docs/
They are still important, but they are not all part of the live request path.
#Important repository observations
-
The repository contains both a general scheduler framework and a more specialized Q-Scheduler framework.
backend/src/schedulers/contains the broader family of scheduling strategies, whilebackend/q_scheduler/contains the newer mission-level planning architecture. -
The dashboard has two data paths.
The main dashboard uses pre-generated JSON files underpublic/data/, while the comparison/training functionality communicates with the FastAPI backend. -
Some runtime inputs are external to the repository.
The API expectsstare/andscan/scenario data directories, but they are not included in the attached copy. -
The project is heavily research-oriented.
The many phase reports, audits, manifests, traces, and statistical outputs show that the authors focused not only on implementing a scheduler but also on proving that it does not use future information and that its reported improvements are reproducible. -
The most important conceptual distinction is immediate reward versus mission value.
The project deliberately moves away from “which channel has the most pulses right now?” toward “which action most improves discovery over the entire mission while preserving coverage?”
In short, this is an adaptive RF surveillance research platform: it simulates a constrained EW receiver, learns or estimates which scan actions are valuable, compares multiple scheduling policies, enforces coverage safety, and exposes the resulting behavior through an operator-style dashboard.