mirror of
https://github.com/macaodha/batdetect2.git
synced 2026-05-23 06:41:53 +02:00
304 lines
7.7 KiB
Python
304 lines
7.7 KiB
Python
import json
|
|
import textwrap
|
|
import uuid
|
|
from pathlib import Path
|
|
|
|
from pydantic import TypeAdapter
|
|
from soundevent import data
|
|
|
|
from batdetect2.core import load_config
|
|
from batdetect2.data.conditions import (
|
|
ClipAnnotationConditionConfig,
|
|
build_clip_annotation_condition,
|
|
)
|
|
|
|
|
|
def load_clip_condition_config(
|
|
tmp_path: Path,
|
|
yaml_string: str,
|
|
) -> ClipAnnotationConditionConfig:
|
|
config_path = tmp_path / f"{uuid.uuid4().hex}.yaml"
|
|
config_path.write_text(textwrap.dedent(yaml_string).strip())
|
|
return load_config(
|
|
config_path, schema=TypeAdapter(ClipAnnotationConditionConfig)
|
|
)
|
|
|
|
|
|
def build_clip_condition_from_yaml(
|
|
tmp_path: Path,
|
|
yaml_string: str,
|
|
base_dir: Path | None = None,
|
|
):
|
|
config = load_clip_condition_config(tmp_path, yaml_string)
|
|
return build_clip_annotation_condition(config, base_dir=base_dir)
|
|
|
|
|
|
def test_recording_satisfies_condition(
|
|
tmp_path: Path,
|
|
create_recording,
|
|
create_clip,
|
|
create_clip_annotation,
|
|
) -> None:
|
|
recording_a = create_recording(path=tmp_path / "a.wav")
|
|
recording_b = create_recording(path=tmp_path / "b.wav")
|
|
clip_a = create_clip(recording_a)
|
|
clip_b = create_clip(recording_b)
|
|
clip_annotation_a = create_clip_annotation(clip_a)
|
|
clip_annotation_b = create_clip_annotation(clip_b)
|
|
ids_path = tmp_path / "recording_ids.json"
|
|
ids_path.write_text(json.dumps([str(recording_a.uuid)]))
|
|
|
|
condition = build_clip_condition_from_yaml(
|
|
tmp_path,
|
|
f"""
|
|
name: recording_satisfies
|
|
condition:
|
|
name: id_in_list
|
|
path: {ids_path}
|
|
""",
|
|
)
|
|
|
|
assert condition(clip_annotation_a)
|
|
assert not condition(clip_annotation_b)
|
|
|
|
|
|
def test_clip_id_in_list_condition(
|
|
tmp_path: Path,
|
|
create_recording,
|
|
create_clip,
|
|
create_clip_annotation,
|
|
) -> None:
|
|
recording_a = create_recording(path=tmp_path / "a.wav")
|
|
recording_b = create_recording(path=tmp_path / "b.wav")
|
|
clip_annotation_a = create_clip_annotation(create_clip(recording_a))
|
|
clip_annotation_b = create_clip_annotation(create_clip(recording_b))
|
|
ids_path = tmp_path / "clip_annotation_ids.json"
|
|
ids_path.write_text(json.dumps([str(clip_annotation_a.uuid)]))
|
|
|
|
condition = build_clip_condition_from_yaml(
|
|
tmp_path,
|
|
f"""
|
|
name: id_in_list
|
|
path: {ids_path}
|
|
""",
|
|
)
|
|
|
|
assert condition(clip_annotation_a)
|
|
assert not condition(clip_annotation_b)
|
|
|
|
|
|
def test_clip_has_tag_conditions(
|
|
tmp_path: Path,
|
|
create_recording,
|
|
create_clip,
|
|
create_clip_annotation,
|
|
) -> None:
|
|
reviewed = data.Tag(key="status", value="reviewed")
|
|
train = data.Tag(key="split", value="train")
|
|
|
|
recording = create_recording(path=tmp_path / "rec.wav")
|
|
clip = create_clip(recording)
|
|
clip_annotation = create_clip_annotation(
|
|
clip,
|
|
clip_tags=[reviewed, train],
|
|
)
|
|
clip_annotation_missing = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[train],
|
|
)
|
|
|
|
condition = build_clip_condition_from_yaml(
|
|
tmp_path,
|
|
"""
|
|
name: has_tag
|
|
tag:
|
|
key: status
|
|
value: reviewed
|
|
""",
|
|
)
|
|
|
|
assert condition(clip_annotation)
|
|
assert not condition(clip_annotation_missing)
|
|
|
|
|
|
def test_clip_has_all_tags_condition(
|
|
tmp_path: Path,
|
|
create_recording,
|
|
create_clip,
|
|
create_clip_annotation,
|
|
) -> None:
|
|
reviewed = data.Tag(key="status", value="reviewed")
|
|
train = data.Tag(key="split", value="train")
|
|
|
|
recording = create_recording(path=tmp_path / "rec.wav")
|
|
clip_annotation = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[reviewed, train],
|
|
)
|
|
clip_annotation_missing = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[reviewed],
|
|
)
|
|
|
|
condition = build_clip_condition_from_yaml(
|
|
tmp_path,
|
|
"""
|
|
name: has_all_tags
|
|
tags:
|
|
- key: status
|
|
value: reviewed
|
|
- key: split
|
|
value: train
|
|
""",
|
|
)
|
|
|
|
assert condition(clip_annotation)
|
|
assert not condition(clip_annotation_missing)
|
|
|
|
|
|
def test_clip_has_any_tag_condition(
|
|
tmp_path: Path,
|
|
create_recording,
|
|
create_clip,
|
|
create_clip_annotation,
|
|
) -> None:
|
|
reviewed = data.Tag(key="status", value="reviewed")
|
|
train = data.Tag(key="split", value="train")
|
|
|
|
recording = create_recording(path=tmp_path / "rec.wav")
|
|
clip_annotation = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[reviewed, train],
|
|
)
|
|
clip_annotation_missing = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[data.Tag(key="split", value="test")],
|
|
)
|
|
|
|
condition = build_clip_condition_from_yaml(
|
|
tmp_path,
|
|
"""
|
|
name: has_any_tag
|
|
tags:
|
|
- key: split
|
|
value: val
|
|
- key: split
|
|
value: train
|
|
""",
|
|
)
|
|
|
|
assert condition(clip_annotation)
|
|
assert not condition(clip_annotation_missing)
|
|
|
|
|
|
def test_clip_all_of_condition(
|
|
tmp_path: Path,
|
|
create_recording,
|
|
create_clip,
|
|
create_clip_annotation,
|
|
) -> None:
|
|
reviewed = data.Tag(key="status", value="reviewed")
|
|
train = data.Tag(key="split", value="train")
|
|
|
|
recording = create_recording(path=tmp_path / "rec.wav")
|
|
clip = create_clip(recording)
|
|
clip_annotation = create_clip_annotation(
|
|
clip,
|
|
clip_tags=[reviewed, train],
|
|
)
|
|
clip_annotation_missing = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[reviewed],
|
|
)
|
|
|
|
condition = build_clip_condition_from_yaml(
|
|
tmp_path,
|
|
"""
|
|
name: all_of
|
|
conditions:
|
|
- name: has_tag
|
|
tag:
|
|
key: status
|
|
value: reviewed
|
|
- name: has_any_tag
|
|
tags:
|
|
- key: split
|
|
value: train
|
|
- key: split
|
|
value: val
|
|
""",
|
|
)
|
|
|
|
assert condition(clip_annotation)
|
|
assert not condition(clip_annotation_missing)
|
|
|
|
|
|
def test_clip_any_of_condition(
|
|
tmp_path: Path,
|
|
create_recording,
|
|
create_clip,
|
|
create_clip_annotation,
|
|
) -> None:
|
|
reviewed = data.Tag(key="status", value="reviewed")
|
|
|
|
recording = create_recording(path=tmp_path / "rec.wav")
|
|
clip_annotation = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[reviewed],
|
|
)
|
|
clip_annotation_missing = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[data.Tag(key="status", value="unchecked")],
|
|
)
|
|
|
|
condition = build_clip_condition_from_yaml(
|
|
tmp_path,
|
|
"""
|
|
name: any_of
|
|
conditions:
|
|
- name: has_tag
|
|
tag:
|
|
key: split
|
|
value: val
|
|
- name: has_tag
|
|
tag:
|
|
key: status
|
|
value: reviewed
|
|
""",
|
|
)
|
|
|
|
assert condition(clip_annotation)
|
|
assert not condition(clip_annotation_missing)
|
|
|
|
|
|
def test_clip_not_condition(
|
|
tmp_path: Path,
|
|
create_recording,
|
|
create_clip,
|
|
create_clip_annotation,
|
|
) -> None:
|
|
recording = create_recording(path=tmp_path / "rec.wav")
|
|
clip_annotation = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[data.Tag(key="split", value="train")],
|
|
)
|
|
clip_annotation_missing = create_clip_annotation(
|
|
create_clip(recording),
|
|
clip_tags=[data.Tag(key="split", value="val")],
|
|
)
|
|
|
|
condition = build_clip_condition_from_yaml(
|
|
tmp_path,
|
|
"""
|
|
name: not
|
|
condition:
|
|
name: has_tag
|
|
tag:
|
|
key: split
|
|
value: val
|
|
""",
|
|
)
|
|
|
|
assert condition(clip_annotation)
|
|
assert not condition(clip_annotation_missing)
|