Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 0 additions & 52 deletions bats_ai/api.py

This file was deleted.

Empty file.
8 changes: 6 additions & 2 deletions bats_ai/core/admin/recording.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from django.contrib import admin, messages
from django.db.models import QuerySet
from django.http import HttpRequest
from django.urls import reverse
from django.utils.html import format_html

from bats_ai.core.models import Recording
from bats_ai.core.tasks.tasks import recording_compute_spectrogram

if TYPE_CHECKING:
from django.db.models import QuerySet
from django.http import HttpRequest


@admin.register(Recording)
class RecordingAdmin(admin.ModelAdmin):
Expand Down
42 changes: 42 additions & 0 deletions bats_ai/core/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations

import logging

from ninja import NinjaAPI
from oauth2_provider.models import AccessToken

from bats_ai.core import views
from bats_ai.core.views import nabat

logger = logging.getLogger(__name__)


def global_auth(request):
if request.user.is_anonymous:
token = request.headers.get("Authorization", "").replace("Bearer ", "")
if len(token) > 0:
try:
access_token = AccessToken.objects.get(token=token)
except AccessToken.DoesNotExist:
access_token = None
if access_token and access_token.user and not access_token.user.is_anonymous:
request.user = access_token.user
user = request.user
return (not user.is_anonymous) and (user.profile.verified or user.is_superuser)


api = NinjaAPI(auth=global_auth)

api.add_router("/recording/", views.recording_router)
api.add_router("/species/", views.species_router)
api.add_router("/grts/", views.grts_cells_router)
api.add_router("/guano/", views.guano_metadata_router)
api.add_router("/recording-annotation/", views.recording_annotation_router)
api.add_router("/export-annotation/", views.export_annotation_router)
api.add_router("/configuration/", views.configuration_router)
api.add_router("/processing-task/", views.processing_task_router)
api.add_router("/recording-tag/", views.recording_tag_router)
api.add_router("/vetting/", views.vetting_router)

api.add_router("/nabat/recording/", nabat.nabat_recording_router)
api.add_router("/nabat/configuration/", nabat.nabat_configuration_router)
2 changes: 1 addition & 1 deletion bats_ai/core/management/commands/copy_recordings.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def handle(self, *args, **options):
new_recording.save()

# Apply a random subset of tags to this recording
k = random.randint(1, len(tag_texts))
k = random.randint(1, len(tag_texts)) # noqa: S311
chosen = random.sample(tag_texts, k=k)
for text in chosen:
tag, _ = RecordingTag.objects.get_or_create(user=owner, text=text)
Expand Down
22 changes: 15 additions & 7 deletions bats_ai/core/management/commands/loadGRTS.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import logging
import os
from pathlib import Path
import tempfile
import urllib
from urllib.request import urlretrieve
import zipfile

from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
import geopandas as gpd
import requests
from tqdm import tqdm # progress bar

from bats_ai.core.models import GRTSCells
Expand Down Expand Up @@ -56,6 +56,12 @@ def add_arguments(self, parser):
"--batch-size", type=int, default=5000, help="Batch size for database insertion"
)

def _download_file(self, url: str, zip_path: Path) -> None:
response = requests.get(url, timeout=120)
response.raise_for_status()
with zip_path.open("wb") as f:
f.write(response.content)

def handle(self, *args, **options):
batch_size = options["batch_size"]

Expand All @@ -65,19 +71,21 @@ def handle(self, *args, **options):
for url, sample_frame_id, name, backup_url in SHAPEFILES:
logger.info("Downloading shapefile for Location %s...", name)
with tempfile.TemporaryDirectory() as tmpdir:
zip_path = os.path.join(tmpdir, "file.zip")
tmpdir = Path(tmpdir)

zip_path = tmpdir / "file.zip"
try:
urlretrieve(url, zip_path)
except urllib.error.URLError as e:
self._download_file(url, zip_path)
except requests.RequestException as e:
logger.warning(
"Failed to download from primary URL: %s. Attempting backup URL...", e
)
if backup_url is None:
logger.warning("No backup URL provided, skipping this shapefile.")
continue
try:
urlretrieve(backup_url, zip_path)
except urllib.error.URLError as e2:
self._download_file(backup_url, zip_path)
except requests.RequestException as e2:
raise CommandError(
f"Failed to download from backup URL as well: {e2}"
) from e2
Expand Down
13 changes: 7 additions & 6 deletions bats_ai/core/management/commands/load_public_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def _try_start_spectrogram_generation(recording_id: int):


def _ingest_files_from_manifest(
*,
s3_client,
bucket: str,
manifest: Path,
Expand Down Expand Up @@ -268,12 +269,12 @@ def handle(self, *args, **options):
if limit:
self.stdout.write(f"Ingesting the first {limit} files from {manifest}...")
_ingest_files_from_manifest(
s3_client,
bucket,
manifest,
owner,
public,
limit,
s3_client=s3_client,
bucket=bucket,
manifest=manifest,
owner=owner,
public=public,
limit=limit,
file_key=file_key,
tag_keys=tag_keys,
)
2 changes: 1 addition & 1 deletion bats_ai/core/models/grts_cells.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class GRTSCells(models.Model):
geom_4326 = models.GeometryField()

@property
def sampleFrameMapping(self):
def sample_frame_mapping(self):
return sample_frame_map[self.sample_frame_id]

@staticmethod
Expand Down
12 changes: 9 additions & 3 deletions bats_ai/core/tasks/export_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
)


def build_filters(filters, has_confidence=False):
def build_filters(filters, *, has_confidence=False):
conditions = {}
if filters.get("start_date"):
conditions["created__date__gte"] = filters["start_date"]
Expand All @@ -37,7 +37,7 @@ def build_filters(filters, has_confidence=False):


def annotation_to_dict(
annotation, include_times=False, include_freqs=False, include_confidence=False
annotation, *, include_times=False, include_freqs=False, include_confidence=False
):
data = {
"id": annotation.id,
Expand Down Expand Up @@ -67,7 +67,13 @@ def annotation_to_dict(


def write_csv_and_json(
zipf, name_prefix, queryset, include_times=False, include_freqs=False, include_confidence=False
zipf,
name_prefix,
queryset,
*,
include_times=False,
include_freqs=False,
include_confidence=False,
):
rows = [
annotation_to_dict(
Expand Down
2 changes: 1 addition & 1 deletion bats_ai/core/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ninja.testing import TestClient
import pytest

from bats_ai.api import api
from bats_ai.core.api import api


@pytest.fixture
Expand Down
1 change: 1 addition & 0 deletions bats_ai/core/utils/contour_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ def extract_contours(

def process_spectrogram_assets_for_contours(
assets: dict[str, Any],
*,
levels_mode: str = "percentile",
percentile_values: list[float] | None = None,
min_area: float = 30.0,
Expand Down
2 changes: 1 addition & 1 deletion bats_ai/core/utils/guano_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def extract_metadata_from_filename(filename: str) -> dict:
return metadata


def extract_guano_metadata(file_path: str | Path, check_filename: bool = False) -> dict:
def extract_guano_metadata(file_path: str | Path, *, check_filename: bool = False) -> dict:
"""Extract GUANO metadata from a WAV file.

Args:
Expand Down
48 changes: 24 additions & 24 deletions bats_ai/core/views/__init__.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
from __future__ import annotations

from .annotations import router as AnnotationRouter
from .configuration import router as ConfigurationRouter
from .export_annotation import router as ExportAnnotationRouter
from .grts_cells import router as GRTSCellsRouter
from .guanometadata import router as GuanoMetadataRouter
from .processing_tasks import router as ProcessingTaskRouter
from .recording import router as RecordingRouter
from .recording_annotation import router as RecordingAnnotationRouter
from .recording_tag import router as RecordingTagRouter
from .sequence_annotations import router as SequenceAnnotationRouter
from .species import router as SpeciesRouter
from .vetting_details import router as VettingRouter
from .annotations import router as annotation_router
from .configuration import router as configuration_router
from .export_annotation import router as export_annotation_router
from .grts_cells import router as grts_cells_router
from .guanometadata import router as guano_metadata_router
from .processing_tasks import router as processing_task_router
from .recording import router as recording_router
from .recording_annotation import router as recording_annotation_router
from .recording_tag import router as recording_tag_router
from .sequence_annotations import router as sequence_annotation_router
from .species import router as species_router
from .vetting_details import router as vetting_router

__all__ = [
"AnnotationRouter",
"ConfigurationRouter",
"ExportAnnotationRouter",
"GRTSCellsRouter",
"GuanoMetadataRouter",
"ProcessingTaskRouter",
"RecordingAnnotationRouter",
"RecordingRouter",
"RecordingTagRouter",
"SequenceAnnotationRouter",
"SpeciesRouter",
"VettingRouter",
"annotation_router",
"configuration_router",
"export_annotation_router",
"grts_cells_router",
"guano_metadata_router",
"processing_task_router",
"recording_annotation_router",
"recording_router",
"recording_tag_router",
"sequence_annotation_router",
"species_router",
"vetting_router",
]
5 changes: 4 additions & 1 deletion bats_ai/core/views/annotations.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from django.http import HttpRequest
from ninja import Schema
from ninja.pagination import RouterPaginated

from bats_ai.core.models import Annotations, Recording

if TYPE_CHECKING:
from django.http import HttpRequest

logger = logging.getLogger(__name__)


Expand Down
5 changes: 4 additions & 1 deletion bats_ai/core/views/export_annotation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from datetime import datetime
import logging
from typing import TYPE_CHECKING

from django.http import JsonResponse
from django.shortcuts import get_object_or_404
Expand All @@ -10,6 +10,9 @@

from bats_ai.core.models import ExportedAnnotationFile

if TYPE_CHECKING:
from datetime import datetime

logger = logging.getLogger(__name__)

router = Router()
Expand Down
8 changes: 6 additions & 2 deletions bats_ai/core/views/guanometadata.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
from __future__ import annotations

from datetime import datetime
import logging
from typing import TYPE_CHECKING

from django.http import HttpRequest, JsonResponse
from ninja import File, Schema
from ninja.files import UploadedFile
from ninja.pagination import RouterPaginated

from bats_ai.core.utils.guano_utils import extract_guano_metadata

if TYPE_CHECKING:
from datetime import datetime

from ninja.files import UploadedFile

router = RouterPaginated()
logger = logging.getLogger(__name__)

Expand Down
Loading
Loading