new plotly and better recording service

This commit is contained in:
mcguirepr89
2022-03-31 08:14:18 -04:00
parent 06eab6b163
commit e5c132edf7
2 changed files with 98 additions and 58 deletions
+2
View File
@@ -10,6 +10,8 @@ fi
[ -z $RECORDING_LENGTH ] && RECORDING_LENGTH=15 [ -z $RECORDING_LENGTH ] && RECORDING_LENGTH=15
if ! pulseaudio --check;then pulseaudio --start;fi
if pgrep arecord &> /dev/null ;then if pgrep arecord &> /dev/null ;then
echo "Recording" echo "Recording"
else else
+96 -58
View File
@@ -5,53 +5,82 @@ import numpy as np
import plotly.graph_objects as go import plotly.graph_objects as go
from plotly.subplots import make_subplots from plotly.subplots import make_subplots
from datetime import timedelta, datetime from datetime import timedelta, datetime
from pathlib import Path
import sqlite3 import sqlite3
from sqlite3 import Connection from sqlite3 import Connection
from pathlib import Path
URI_SQLITE_DB = "/home/pi/BirdNET-Pi/scripts/birds.db" URI_SQLITE_DB = "/home/pi/BirdNET-Pi/scripts/birds.db"
st.set_page_config(layout='wide') st.set_page_config(layout='wide')
@st.cache(ttl=60,hash_funcs={Connection: id})
def get_connection(path: str):
"""Put the connection in cache to reuse if path does not change between Streamlit reruns.
NB : https://stackoverflow.com/questions/48218065/programmingerror-sqlite-objects-created-in-a-thread-can-only-be-used-in-that-sa
"""
return sqlite3.connect(path, check_same_thread=False)
# Remove whitespace from the top of the page and sidebar
st.markdown("""
<style>
.css-18e3th9 {
padding-top: 2.5rem;
padding-bottom: 10rem;
padding-left: 5rem;
padding-right: 5rem;
}
.css-1d391kg {
padding-top: 3.5rem;
padding-right: 1rem;
padding-bottom: 3.5rem;
padding-left: 1rem;
}
</style>
""", unsafe_allow_html=True)
col1,col2,col3 = st.columns([20,20,20])
col1.title('BirdNET-Pi', anchor=None)
col2.image('/home/pi/BirdNET-Pi/homepage/images/bird.png')
col3.text('')
@st.cache(hash_funcs={Connection: id})
def get_connection(path:str):
return sqlite3.connect(path,check_same_thread=False)
# def load_data():
# df1 = pd.read_csv('/home/pi/BirdNET-Pi/BirdDB.txt', sep=';')
# return df1
def get_data(conn: Connection): def get_data(conn: Connection):
df1 = pd.read_sql("SELECT * FROM detections", con=conn) df1=pd.read_sql("SELECT * FROM detections", con=conn)
return df1 return df1
conn = get_connection(URI_SQLITE_DB) conn = get_connection(URI_SQLITE_DB)
#@st.cache()
#def load_data():
# df1 = pd.read_csv('/home/pi/BirdNET-Pi/BirdDB.txt', sep=';')
# return df1
# Read in the cereal data # Read in the cereal data
#df = load_data() # df = load_data()
df = get_data(conn) df=get_data(conn)
df2=df.copy() df2=df.copy()
df2['DateTime']=pd.to_datetime(df2['Date'] + " " + df2['Time']) df2['DateTime']=pd.to_datetime(df2['Date'] + " " + df2['Time'])
df2=df2.set_index('DateTime') df2=df2.set_index('DateTime')
# Filter on date range # Filter on date range
# Date as calendars # Date as calendars
#Start_Date1 = pd.to_datetime(st.sidebar.date_input('Which date do you want to start?', value = df2.index.min())) # Start_Date = pd.to_datetime(st.sidebar.date_input('Which date do you want to start?', value = df2.index.min()))
#End_Date1 = pd.to_datetime(st.sidebar.date_input('Which date do you want to end?', value = df2.index.max())) # End_Date = pd.to_datetime(st.sidebar.date_input('Which date do you want to end?', value = df2.index.max()))
# Date as slider # Date as slider
Start_Date = pd.to_datetime(df2.index.min()) Start_Date = pd.to_datetime(df2.index.min()).date()
End_Date = pd.to_datetime(df2.index.max()) End_Date = pd.to_datetime(df2.index.max()).date()
Date_Slider = st.sidebar.slider('Date Range', Date_Slider = st.slider('Date Range',
value=(Start_Date.to_pydatetime(), min_value = Start_Date-timedelta(days=1),
End_Date.to_pydatetime()) max_value = End_Date,
value=(Start_Date,
End_Date)
) )
filt = (df2.index >= Date_Slider[0]) & (df2.index <= Date_Slider[1]+timedelta(days=1))
filt = (df2.index >= pd.Timestamp(Date_Slider[0])) & (df2.index <= pd.Timestamp(Date_Slider[1]+timedelta(days=1)))
df2 = df2[filt] df2 = df2[filt]
#Create species count for selected date range #Create species count for selected date range
@@ -61,22 +90,24 @@ Specie_Count=df2['Com_Name'].value_counts()
#Create species treemap #Create species treemap
# Create Hourly Crosstab # Create Hourly Crosstab
hourly=pd.crosstab(df2['Com_Name'],df2.index.hour, dropna=False) hourly=pd.crosstab(df2['Com_Name'],df2.index.hour, dropna=False)
# Filter on species # Filter on species
species = list(hourly.index) species = list(hourly.index)
top_N = st.sidebar.select_slider( cols1,cols2= st.columns((1,1))
top_N = cols1.slider(
'Select Number of Birds to Show', 'Select Number of Birds to Show',
list(range(1,len(Specie_Count))), min_value = 1,
value=min(10,len(Specie_Count)-1)) value=min(10,len(Specie_Count))
)
top_N_species = (df2['Com_Name'].value_counts()[:top_N]) top_N_species = (df2['Com_Name'].value_counts()[:top_N])
specie = st.sidebar.selectbox('Which bird would you like to explore?', species, index=species.index(list(top_N_species.index)[0])) specie = cols2.selectbox('Which bird would you like to explore for the dates '+str(Date_Slider[0])+' to '+str(Date_Slider[1])+'?', species,
index=species.index(list(top_N_species.index)[0]))
font_size=15 font_size=15
@@ -87,60 +118,67 @@ filt=df2['Com_Name']==specie
df_counts=df2[filt].resample('D').count() df_counts=df2[filt].resample('D').count()
fig = make_subplots( fig = make_subplots(
rows=2, cols =2, rows=3, cols =2,
specs= [[{"type":"xy","rowspan":2}, {"type":"polar"}], [None, {"type":"xy"}]], specs= [[{"type":"xy","rowspan":3}, {"type":"polar","rowspan":2}], [{"rowspan":1}, {"rowspan":1} ], [None, {"type":"xy","rowspan":1}]],
subplot_titles=('<b style="font-size:x-large;">Species in Date Range</b>', subplot_titles=('<b>Top '+ str(top_N) + ' Species in Date Range '+str(Date_Slider[0])+' to '+str(Date_Slider[1])+'</b>',
'<b style="font-size:large;">'+specie+'</b><br>' 'Total Detect:'+str('{:,}'.format(sum(df_counts.Time)))+
'<span style="font-size:medium;">Total Detections: '+str('{:,}'.format(sum(df_counts.Time)))+'<br>' ' Confidence Max:'+str('{:.2f}%'.format(max(df2[df2['Com_Name']==specie]['Confidence'])*100))+
'Max Confidence: '+str('{:.2f}%'.format(max(df2[df2['Com_Name']==specie]['Confidence'])*100))+'<br>' ' '+' Median:'+str('{:.2f}%'.format(np.median(df2[df2['Com_Name']==specie]['Confidence'])*100))
'Median Confidence: '+str('{:.2f}%'.format(np.median(df2[df2['Com_Name']==specie]['Confidence'])*100))+'</span>'
) )
) )
# fig.layout.height=900 fig.layout.annotations[1].update(x=0.7,y=0.25, font_size=15)
# fig.layout.width=1500
#Plot seen species for selected date range and number of species #Plot seen species for selected date range and number of species
fig.add_trace(go.Bar(y=top_N_species.index, x=top_N_species, orientation='h'), row=1,col=1) fig.add_trace(go.Bar(y=top_N_species.index, x=top_N_species, orientation='h'), row=1,col=1)
fig.update_layout( fig.update_layout(
margin=dict(l=0, r=50, t=70, b=0), margin=dict(l=0, r=0, t=50, b=0),
yaxis={'categoryorder':'total ascending'}) yaxis={'categoryorder':'total ascending'})
# Set 360 degrees, 24 hours for polar plot # Set 360 degrees, 24 hours for polar plot
theta = np.linspace(0.0, 360, 24, endpoint=False) theta = np.linspace(0.0, 360, 24, endpoint=False)
d=pd.DataFrame(np.zeros((23,1))).squeeze() d=pd.DataFrame(np.zeros((23,1))).squeeze()
radius = hourly.loc[specie] detections = hourly.loc[specie]
radius=(d+radius).fillna(0) detections=(d+detections).fillna(0)
fig.add_trace(go.Barpolar(r = radius, theta=theta), row=1, col=2) fig.add_trace(go.Barpolar(r = detections, theta=theta), row=1, col=2)
fig.update_layout( fig.update_layout(
autosize=True, autosize=False,
width = 1000, width = 1000,
height = 750, height = 500,
showlegend=False, showlegend=False,
polar = dict( polar = dict(
radialaxis = dict( radialaxis = dict(
tickfont_size = font_size, tickfont_size = font_size,
showticklabels = False), showticklabels = True,
hoverformat = "#%{theta}: <br>Popularity: %{percent} </br> %{r}"
),
angularaxis = dict( angularaxis = dict(
tickfont_size= font_size, tickfont_size= font_size,
rotation = -90, rotation = -90,
direction = 'clockwise', direction = 'clockwise',
tickmode='array', tickmode='array',
tickvals=[0,45,90,135,180,225,270,315], tickvals=[0,15,35,45,60,75,90,105,120,135,150,165,180,195,210,225,240,255,270,285,300,315,330,345],
ticktext=['12am','3am', '6am','9am','12pm','3pm', '6pm','9pm'], ticktext=['12am','1am','2am','3am','4am','5am', '6am','7am','8am','9am','10am','11am','12pm','1pm','2pm','3pm','4pm','5pm', '6pm','7pm','8pm','9pm','10pm','11pm'],
hoverformat = ""#"%{theta}: <br>Popularity: %{percent} </br> %{r}" hoverformat = "#%{theta}: <br>Popularity: %{percent} </br> %{r}"
), ),
), ),
) )
fig.layout.annotations[1].update(x=0.775,y=0.4, font_size=15)
x=df_counts.index
y=df_counts['Com_Name']
fig.add_trace(go.Bar(x=df_counts.index,y=df_counts['Time']), row=2, col=2) daily=pd.crosstab(df2['Com_Name'],df2.index.date, dropna=False)
container=st.container() fig.add_trace(go.Bar(x=daily.columns, y=daily.loc[specie]), row=3, col=2)
container.plotly_chart(fig, use_container_width=True)
# container=st.container()
# config={'displayModelBar': False}
st.plotly_chart(fig, use_container_width=True) #, config=config)
# cols3,cols4=st.columns((1,1))
#
# extract_date=Date_Slider
#
# audio_file = open('/home/pi/BirdSongs/Extracted/By_Date/2022-03-22/Yellow-streaked_Greenbul/Yellow-streaked_Greenbul-77-2022-03-22-birdnet-15:04:28.mp3', 'rb')
# audio_bytes = audio_file.read()
# cols4.audio(audio_bytes, format='audio/mp3')