mirror of
https://github.com/macaodha/batdetect2.git
synced 2026-01-10 17:19:34 +01:00
Add example plotting notebook
This commit is contained in:
parent
374c62d7ab
commit
2308ea83a3
273
notebooks/plotting.py
Normal file
273
notebooks/plotting.py
Normal file
@ -0,0 +1,273 @@
|
||||
import marimo
|
||||
|
||||
__generated_with = "0.14.16"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from batdetect2.data import load_dataset_config, load_dataset
|
||||
from batdetect2.preprocess import load_preprocessing_config, build_preprocessor
|
||||
from batdetect2 import api
|
||||
from soundevent import data
|
||||
from batdetect2.evaluate.types import MatchEvaluation
|
||||
from batdetect2.types import Annotation
|
||||
from batdetect2.compat import annotation_to_sound_event_prediction
|
||||
from batdetect2.plotting import (
|
||||
plot_clip,
|
||||
plot_clip_annotation,
|
||||
plot_clip_prediction,
|
||||
plot_matches,
|
||||
plot_false_positive_match,
|
||||
plot_false_negative_match,
|
||||
plot_true_positive_match,
|
||||
plot_cross_trigger_match,
|
||||
)
|
||||
return (
|
||||
MatchEvaluation,
|
||||
annotation_to_sound_event_prediction,
|
||||
api,
|
||||
build_preprocessor,
|
||||
data,
|
||||
load_dataset,
|
||||
load_dataset_config,
|
||||
load_preprocessing_config,
|
||||
plot_clip_annotation,
|
||||
plot_clip_prediction,
|
||||
plot_cross_trigger_match,
|
||||
plot_false_negative_match,
|
||||
plot_false_positive_match,
|
||||
plot_matches,
|
||||
plot_true_positive_match,
|
||||
)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(build_preprocessor, load_dataset_config, load_preprocessing_config):
|
||||
dataset_config = load_dataset_config(
|
||||
path="example_data/config.yaml", field="datasets.train"
|
||||
)
|
||||
|
||||
preprocessor_config = load_preprocessing_config(
|
||||
path="example_data/config.yaml", field="preprocess"
|
||||
)
|
||||
|
||||
preprocessor = build_preprocessor(preprocessor_config)
|
||||
return dataset_config, preprocessor
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(dataset_config, load_dataset):
|
||||
dataset = load_dataset(dataset_config)
|
||||
return (dataset,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(dataset):
|
||||
clip_annotation = dataset[1]
|
||||
return (clip_annotation,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(clip_annotation, plot_clip_annotation, preprocessor):
|
||||
plot_clip_annotation(
|
||||
clip_annotation, preprocessor=preprocessor, figsize=(15, 5)
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(annotation_to_sound_event_prediction, api, clip_annotation, data):
|
||||
audio = api.load_audio(clip_annotation.clip.recording.path)
|
||||
detections, features, spec = api.process_audio(audio)
|
||||
clip_prediction = data.ClipPrediction(
|
||||
clip=clip_annotation.clip,
|
||||
sound_events=[
|
||||
annotation_to_sound_event_prediction(
|
||||
prediction, clip_annotation.clip.recording
|
||||
)
|
||||
for prediction in detections
|
||||
],
|
||||
)
|
||||
return (clip_prediction,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(clip_prediction, plot_clip_prediction):
|
||||
plot_clip_prediction(clip_prediction, figsize=(15, 5))
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from batdetect2.evaluate import match_predictions_and_annotations
|
||||
import random
|
||||
return match_predictions_and_annotations, random
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(data, random):
|
||||
def add_noise(clip_annotation, time_buffer=0.003, freq_buffer=1000):
|
||||
def _add_bbox_noise(bbox):
|
||||
start_time, low_freq, end_time, high_freq = bbox.coordinates
|
||||
return data.BoundingBox(
|
||||
coordinates=[
|
||||
start_time + random.uniform(-time_buffer, time_buffer),
|
||||
low_freq + random.uniform(-freq_buffer, freq_buffer),
|
||||
end_time + random.uniform(-time_buffer, time_buffer),
|
||||
high_freq + random.uniform(-freq_buffer, freq_buffer),
|
||||
]
|
||||
)
|
||||
|
||||
def _add_noise(se):
|
||||
return se.model_copy(
|
||||
update=dict(
|
||||
sound_event=se.sound_event.model_copy(
|
||||
update=dict(
|
||||
geometry=_add_bbox_noise(se.sound_event.geometry)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return clip_annotation.model_copy(
|
||||
update=dict(
|
||||
sound_events=[
|
||||
_add_noise(se) for se in clip_annotation.sound_events
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def drop_random(obj, p=0.5):
|
||||
return obj.model_copy(
|
||||
update=dict(
|
||||
sound_events=[se for se in obj.sound_events if random.random() > p]
|
||||
)
|
||||
)
|
||||
return add_noise, drop_random
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
add_noise,
|
||||
clip_annotation,
|
||||
clip_prediction,
|
||||
drop_random,
|
||||
match_predictions_and_annotations,
|
||||
):
|
||||
|
||||
|
||||
matches = match_predictions_and_annotations(
|
||||
drop_random(add_noise(clip_annotation), p=0.2),
|
||||
drop_random(clip_prediction),
|
||||
)
|
||||
return (matches,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(clip_annotation, matches, plot_matches):
|
||||
plot_matches(matches, clip_annotation.clip, figsize=(15, 5))
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(matches):
|
||||
true_positives = []
|
||||
false_positives = []
|
||||
false_negatives = []
|
||||
|
||||
for match in matches:
|
||||
if match.source is None and match.target is not None:
|
||||
false_negatives.append(match)
|
||||
elif match.target is None and match.source is not None:
|
||||
false_positives.append(match)
|
||||
elif match.target is not None and match.source is not None:
|
||||
true_positives.append(match)
|
||||
else:
|
||||
continue
|
||||
|
||||
return false_negatives, false_positives, true_positives
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MatchEvaluation, false_positives, plot_false_positive_match):
|
||||
false_positive = false_positives[0]
|
||||
false_positive_eval = MatchEvaluation(
|
||||
match=false_positive,
|
||||
gt_det=False,
|
||||
gt_class=None,
|
||||
pred_score=false_positive.source.score,
|
||||
pred_class_scores={
|
||||
"myomyo": 0.2
|
||||
}
|
||||
)
|
||||
|
||||
plot_false_positive_match(false_positive_eval)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MatchEvaluation, false_negatives, plot_false_negative_match):
|
||||
false_negative = false_negatives[0]
|
||||
false_negative_eval = MatchEvaluation(
|
||||
match=false_negative,
|
||||
gt_det=True,
|
||||
gt_class="myomyo",
|
||||
pred_score=None,
|
||||
pred_class_scores={}
|
||||
)
|
||||
|
||||
plot_false_negative_match(false_negative_eval)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MatchEvaluation, plot_true_positive_match, true_positives):
|
||||
true_positive = true_positives[0]
|
||||
true_positive_eval = MatchEvaluation(
|
||||
match=true_positive,
|
||||
gt_det=True,
|
||||
gt_class="myomyo",
|
||||
pred_score=0.87,
|
||||
pred_class_scores={
|
||||
"pyomyo": 0.84,
|
||||
"pippip": 0.84,
|
||||
}
|
||||
)
|
||||
|
||||
plot_true_positive_match(true_positive_eval)
|
||||
return (true_positive,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MatchEvaluation, plot_cross_trigger_match, true_positive):
|
||||
cross_trigger_eval = MatchEvaluation(
|
||||
match=true_positive,
|
||||
gt_det=True,
|
||||
gt_class="myomyo",
|
||||
pred_score=0.87,
|
||||
pred_class_scores={
|
||||
"pippip": 0.84,
|
||||
"myomyo": 0.84,
|
||||
}
|
||||
)
|
||||
|
||||
plot_cross_trigger_match(cross_trigger_eval)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
Loading…
Reference in New Issue
Block a user