Monday 29 January 2024

BirdNet-Pi Portable: chart info mods

My BirdNet-Pi Portable system gets taken to places away from home!

So its important that the daily records are properly labeled.

BirdNet-Pi has a feature called Daily Charts, which for my base station is quite straightforward; i.e. all charts are for my home location.

But for my portable system, these charts currently cover various locations in southern England. So I needed some way to mark them with the actual location.

I also vary the detection Confidence threshold from time to time, so wanted to also include this.

the code

The location & confidence threshold information that is needed is contained in the birdnet.conf file.

So here is a simple modification to the file that meets my needs.

The darker text lines contain modifications, while the lighter text is for context/positioning within the file. Red text just contains comments & marker lines:-

import sqlite3
import os
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
from datetime import datetime
import textwrap
import matplotlib.font_manager as font_manager
from matplotlib import rcParams

import configparser
import itertools

def GetConfigData(key):
    config = configparser.ConfigParser()
    filename = userDir + '/BirdNET-Pi/birdnet.conf'   
    with open(filename) as fp:
        config.read_file(itertools.chain(['[global]'], fp), source=filename)
        keyData = config.get('global', key)
    return keyData

userDir = os.path.expanduser('~')

myVar = GetConfigData("CONFIDENCE")
myConfidence = 'Confidence => ' + str(int(float(myVar) * 100)) + '%'
myLocation = GetConfigData("SITE_NAME")


conn = sqlite3.connect(userDir + '/BirdNET-Pi/scripts/birds.db')
df = pd.read_sql_query("SELECT * from detections", conn)
cursor = conn.cursor()


I'd previously modified this file to display up to the last 25 unique detections:-

cursor.execute('SELECT DISTINCT (Com_Name) FROM detections WHERE Date = DATE(\'now\', \'localtime\')')
uTable_rows = len(cursor.fetchall())

# Get todays readings
now =
df_plt_today = df_plt[df_plt['Date'] == now.strftime("%Y-%m-%d")]

# Set number of top species to report
readings = 25
if uTable_rows > readings:
gy = 0.4 * gy


plt_top10_today = (df_plt_today['Com_Name'].value_counts()[:readings])
df_plt_top10_today = df_plt_today[df_plt_today.Com_Name.isin(plt_top10_today.index)]

if df_plt_top10_today.empty:

# Set Palette for graphics
pal = "Blues"

# Set up plot axes and titles

f, axs = plt.subplots(1, 2, figsize=(10, gy), gridspec_kw=dict(width_ratios=[3, 6]), facecolor='#77C487')
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0, hspace=0)

# generate y-axis order for all figures based on frequency

Its then just a matter of modifying the line that displays the chart title, something like this:-

# Set combined plot layout and titles


plt.suptitle(str(uTable_rows) + " species detected at " + myLocation + " with " + myConfidence + " on "  +  str(now.strftime("%d-%b-%Y")) + ", last update: " + str(now.strftime("%H:%M")) + "\r")

# Save combined plot

The GetConfigData routine allows you to get any value from the available key-value pairs in the birdnet configuration file. Its then up to you how you display this.

the results

The Daily Charts are basically copies of the Overview screen, so Daily Charts now typically look like this:-

One mod left to do is to get the lat/lon coordinates from the entered place name, as I currently have to do this manually.

No comments:

Post a Comment