Pycom helps you detect and identify signals visible on the waterfall display. The system has two layers:
- Signal Detection — automatically finds signals that stand out above the noise, using statistical analysis (no machine learning required)
- Signal Identification (AI) — classifies detected signals by type (CW, FT8, FM, etc.), using a trained neural network model — this page
AI Signal Identification
Detected signals can be classified by the AI signal identifier, which analyzes the shape and timing patterns visible around each signal on the waterfall, plus contextual information (frequency span, noise floor, bandwidth, SNR, etc.).
The classifier outputs a confidence score for each signal type. Results below 50% confidence are displayed as "Unknown". The default model recognizes 15 signal types (although there is minimal training data in the distributed base model for some of the signal types presently; this will improve in time):
| Recognized Signal Types | ||||
|---|---|---|---|---|
| CW | FM | AM | SSB | RTTY |
| FT8 | FT4 | FT2 | Q65 | JT65 |
| AFSK | PSK | FSK | MFSK | MSK |
The bundled model achieves 81% validation accuracy. After fine-tuning with your own captures, you may have additional types. See the Signal Mode Reference for detailed modulation characteristics, bandwidths, and typical uses of each mode.
Capture Window
The Capture button (camera icon) on the waterfall display opens a capture window with a frozen snapshot of the current waterfall and equalizer. This is where you review, label, and save signals for training.
- Detected signals appear as orange vertical lines on the waterfall
- Drag on the waterfall to manually add a signal candidate at a specific frequency range
- Each candidate has a label dropdown containing all model classes plus "Unknown"
- The AI auto-classifies all detected candidates when the capture window opens
- Save stores the capture as a
.npzfile in~/Pycom/signals/captures/
How Labels Work
Labels are stored in capture metadata. During training, the script reads each capture's metadata and chooses the label in this priority order:
- user_label — if you manually selected a label, that label is always used
- ai_label — if the AI classified the signal with high confidence that classification is used
Browsing Saved Captures
| Button | Action |
|---|---|
| Prev / Next | Navigate through previously saved captures |
| Update | Save label or note changes to an existing capture |
| Delete | Permanently remove a capture from disk |
Model Training
To improve signal classification accuracy or add new signal types, train the model on your own labeled captures. The more labeled captures you have across different signal types, the better the classifier performs.
Prerequisites
- Python 3.10+
- Training dependencies: Run
pip install torch onnx onnxscript torchvisionbefore training
Getting the Training Scripts
- Open Configuration → Signal Detection tab
- Click Download Training Resources
- Existing scripts will be overwritten — back up any custom changes first
- Scripts are deployed to
~/Pycom/signals/scripts/
Training from Scratch
Train a new model with random initial weights:
macOS/Linux:
cd ~/Pycom/signals/scripts
python3 retrain_model.py
Windows:
cd %USERPROFILE%\Pycom\signals\scripts
python retrain_model.py
Fine-Tuning from the Base Model
Fine-tune when you want to add your signal captures to the distributed base model. This preserves the base model's existing knowledge while adapting it for your signals.
macOS/Linux:
cd ~/Pycom/signals/scripts
python3 retrain_model.py --fine-tune --freeze-classifier-input
Windows:
cd %USERPROFILE%\Pycom\signals\scripts
python retrain_model.py --fine-tune --freeze-classifier-input
The --fine-tune flag always loads from the protected factory default model, ensuring consistent results regardless of any previous training.
Training Flags
| Flag | What It Does |
|---|---|
--fine-tune | Fine-tune from the distributed base model. Always loads the protected .default model and labels. |
--freeze-classifier-input | Freezes nearly all of the model, training only the new-class rows of the final classification layer. Best for small datasets with new classes. |
--freeze-features | Freezes only the early visual analysis layers. Use only with large datasets. |
--checkpoint | Saves an additional .pt file for future training with train_signal_classifier.py --resume. |
--epochs N | Training epochs (default: 30). |
--lr VALUE | Learning rate override. |
Quality Warnings
The retrain script checks your training data and warns about:
- Sample regression — fine-tuning with far fewer samples than the base model was trained on
- Low class coverage — fewer than 33% of classes have training data
- Class imbalance — any single class exceeds 50% of total training samples
- Weak base model — the current model was trained from scratch with very few samples
Validation accuracy warnings appear when trained on fewer than 10 samples, indicating results may not generalize reliably.
Protected Default Model
When the app first deploys the bundled default model, it also creates protected copies:
signal_classifier.onnx.defaultsignal_labels.json.default
These copies are never overwritten by training scripts. If a bad training run degrades the model, you can always recover by fine-tuning again from the defaults. The --fine-tune flag always uses these files.
File Locations
| Item | Location | Purpose |
|---|---|---|
| AI model | ~/Pycom/signals/model/signal_classifier.onnx | The trained model file |
| Labels + metadata | ~/Pycom/signals/model/signal_labels.json | Signal type names, training metadata, and model config |
| Protected defaults | ~/Pycom/signals/model/*.default | Factory default model + labels (never overwritten by training) |
| Captures | ~/Pycom/signals/captures/*.npz | Your saved signal captures |
| Training scripts | ~/Pycom/signals/scripts/ | Training, model definition, and retrain scripts |
If no user-trained model exists, the app deploys the bundled default model on start up. User-trained models are never overwritten by this process.