Automated biological validation for BirdNET acoustic monitoring using taxonomic rules
Praven Pro automatically validates BirdNET detections using biological rules, not machine learning. The system catches false positives that BirdNET misses by checking if detections are biologically plausible:
BirdNET CSV → Praven Validator → Accept/Review/Reject
↓
┌───────────┼───────────┐
│ │ │
Geographic Temporal Habitat
Validator Validator Validator
↓ ↓ ↓
eBird API Species DB Habitat DB
GBIF API (diurnal/ (preferences)
nocturnal)
pip install -r requirements.txt
Validate any BirdNET CSV file with a single command:
python validate.py your_detections.csv \
--lat 63.341 --lon 10.215 \
--habitat wetland \
--date 2025-10-13
Output: Automatically creates accepted.csv, rejected.csv, review.csv, and summary.txt
from praven.validator import BiologicalValidator
from praven.config import ValidationConfig
# Initialize validator (auto-preloads eBird data)
config = ValidationConfig(
location=(63.341, 10.215), # Gaulosen coordinates
date="2025-10-13",
habitat_type="wetland",
weather_conditions={"rain": 0.8, "fog": 0.7}
)
validator = BiologicalValidator(config)
# Validate BirdNET detection
result = validator.validate_detection(
species="Lesser Spotted Woodpecker",
timestamp="2025-10-13 23:45:00",
confidence=0.85
)
print(result.status) # "REJECT"
print(result.reason) # "Nocturnal impossibility: diurnal species at 23:45"
Tested on the Gaulossen Nature Reserve dataset (October 2025):
⚠️ Current Limitations: This system is a proof-of-concept validated on a single wetland study. Extensive development is required for broader real-world deployment, including:
praven-pro/
├── praven/
│ ├── __init__.py
│ ├── validator.py # Main validation engine
│ ├── api/
│ │ ├── ebird_client.py # eBird API wrapper
│ │ ├── gbif_client.py # GBIF API wrapper
│ │ └── cache.py # API response caching
│ ├── rules/
│ │ ├── geographic.py # Geographic range validation
│ │ ├── temporal.py # Time-of-day, seasonality
│ │ ├── habitat.py # Habitat matching
│ │ └── weather.py # Weather-activity ML model
│ ├── models/
│ │ ├── weather_model.py # Random Forest weather model
│ │ └── training.py # Model training pipeline
│ ├── data/
│ │ ├── species_db.json # Species metadata (diurnal/nocturnal)
│ │ └── habitat_db.json # Habitat preferences
│ └── config.py # Configuration management
├── examples/
│ ├── validate_birdnet_csv.py
│ └── train_weather_model.py
├── tests/
│ └── test_validator.py
├── requirements.txt
└── README.md
export EBIRD_API_KEY="your-key"from praven.validator import BiologicalValidator
import pandas as pd
# Load BirdNET results
birdnet_df = pd.read_csv("BirdNET_results.txt", sep="\t")
validator = BiologicalValidator.from_config({
"location": (63.341, 10.215),
"date_range": ("2025-10-13", "2025-10-15"),
"habitat_type": "wetland",
"weather": {"rain": 0.8, "fog": 0.7}
})
# Validate all detections
results = validator.validate_dataframe(birdnet_df)
# Filter by status
accepted = results[results.status == "ACCEPT"]
rejected = results[results.status == "REJECT"]
needs_review = results[results.status == "REVIEW"]
print(f"Accepted: {len(accepted)}")
print(f"Rejected: {len(rejected)}")
print(f"Needs Review: {len(needs_review)}")
# Export rejection reasons
rejected[["species", "timestamp", "rejection_reason"]].to_csv("rejected.csv")
Original Manual Validation:
The system identified these biologically implausible detections:
from praven.models.training import WeatherModelTrainer
# Load your verified dataset
trainer = WeatherModelTrainer()
trainer.load_verified_data("gaulossen_verified.csv")
# Train model on weather-activity patterns
model = trainer.train(
features=["rain_intensity", "fog_density", "temperature", "hour"],
target="detection_valid"
)
# Save model
model.save("custom_weather_model.pkl")
# Use in validator
validator = BiologicalValidator(
config=config,
custom_weather_model="custom_weather_model.pkl"
)
Redpath, G. (2025). Praven Pro: Automated Biological Validation for
BirdNET Acoustic Monitoring. GitHub. https://github.com/Ziforge/praven-pro
Non-Commercial Use Only
Praven Pro is free for academic research, educational purposes, and non-profit conservation work.
Commercial use requires a separate license. For commercial licensing inquiries, please contact:
See LICENSE for full terms.