Skip to content

Commit 71b2c07

Browse files
initial nabat models/api script (#122)
* initial nabat models/api script * model updates and reset endpoints * outlining tasks * nabat retrieval logic * NABat ingestion working * rename acoustic_batch_initialize * remove flower, add spectrogram viewer script, move spectrogram creation to tasks, update NABat spectro generating process * nabat integration * deduplicating functions * add species manual and auto ids to nabat retrieval * non-compressed X-axis highlight, zooming legend fix, 2.5x default compressed * cursor time compressed fix, axis length fix, edit column reorder in Recordings * recording annotation details * removing some commented out emits * remove footer from details for inference annotations * Ignore egg-info directories * Add additional configuration settings * Add new settings to admin page * Use configuration to set `compressed` ref * Move save button closer to settings * Check config setting before running inference * Use config setting for initial compressed scale * reference the outputs.tags instead of outputs.results * renames acoustic batch to recording (#128) * renames acoustic batch to recording based on conversations * add migrations * Use slider for stretch setting * recording based nabat spectrograms * migrations modifications * public apis, adding apiToken access control * recording annotation endpoints * nabat local annotaitons * precition config, requesting annotations, updating species * swapping to user_email from user_id * pushing annotations back * auth cleanup * convert to mutation * Update scripts/USGS/naBatSpecies.py Co-authored-by: Michael Nagler <mike.nagler@kitware.com> * addressing some of the comments * enum for processing task types, processing task get_or_create * client_id option, base environment file, updating instructions, NABAT_API_URL environment value * SSL verification hack * fixing get_or_create for processing tasks in celery tasks * resolve lint warnings * swap to logger.error in nabat recording creation --------- Co-authored-by: naglepuff <mike.nagler@kitware.com>
1 parent 6308d1b commit 71b2c07

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+4223
-358
lines changed

DEPLOYMENT.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ to `.env` and change the default passwords for fields
4545
to collect the static files
4646
6. Run `docker compose -f docker-compose.prod.yml up` to start the server
4747
add `-d` for a silent version to run in the background
48-
7. Change the ID in the `./client/env.production` to a custom ID - this will
48+
7. **OPTIONAL** Change the ID in the `./client/env.production` to a custom ID - this will
4949
probably require a `docker compose -f docker-compose.prod.yml build` \
50-
to build the app afterwards
50+
to build the app afterwards. This Id is used to indetify the application and
51+
isn't required to be changed especially if the building of the client is done
52+
outside of deployment.
5153
8. After creating the basic application log into the django admin `batdetectai.kitware.com/admin`
5254
and change the ApplicationId to the ID in the `./client.env.production`
5355
9. Test logging in/out and uploading data to the server.

bats_ai/api.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
ConfigurationRouter,
88
GRTSCellsRouter,
99
GuanoMetadataRouter,
10+
ProcessingTaskRouter,
1011
RecordingAnnotationRouter,
1112
RecordingRouter,
1213
SpeciesRouter,
1314
)
15+
from bats_ai.core.views.nabat import NABatConfigurationRouter, NABatRecordingRouter
1416

1517
logger = logging.getLogger(__name__)
1618

@@ -37,3 +39,6 @@ def global_auth(request):
3739
api.add_router('/guano/', GuanoMetadataRouter)
3840
api.add_router('/recording-annotation/', RecordingAnnotationRouter)
3941
api.add_router('/configuration/', ConfigurationRouter)
42+
api.add_router('/processing-task/', ProcessingTaskRouter)
43+
api.add_router('/nabat/recording/', NABatRecordingRouter)
44+
api.add_router('/nabat/configuration/', NABatConfigurationRouter)

bats_ai/core/admin/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
from .annotations import AnnotationsAdmin
22
from .compressed_spectrogram import CompressedSpectrogramAdmin
3+
from .configuration import ConfigurationAdmin
34
from .grts_cells import GRTSCellsAdmin
45
from .image import ImageAdmin
6+
from .nabat.admin import (
7+
NABatCompressedSpectrogramAdmin,
8+
NABatRecordingAdmin,
9+
NABatRecordingAnnotationAdmin,
10+
NABatSpectrogramAdmin,
11+
)
12+
from .processing_task import ProcessingTaskAdmin
513
from .recording import RecordingAdmin
614
from .recording_annotations import RecordingAnnotationAdmin
715
from .species import SpeciesAdmin
@@ -18,4 +26,11 @@
1826
'GRTSCellsAdmin',
1927
'CompressedSpectrogramAdmin',
2028
'RecordingAnnotationAdmin',
29+
'ProcessingTaskAdmin',
30+
'ConfigurationAdmin',
31+
# NABat Models
32+
'NABatRecordingAnnotationAdmin',
33+
'NABatCompressedSpectrogramAdmin',
34+
'NABatSpectrogramAdmin',
35+
'NABatRecordingAdmin',
2136
]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from django.contrib import admin
2+
3+
from bats_ai.core.models.configuration import Configuration
4+
5+
6+
@admin.register(Configuration)
7+
class ConfigurationAdmin(admin.ModelAdmin):
8+
list_display = (
9+
'display_pulse_annotations',
10+
'display_sequence_annotations',
11+
'run_inference_on_upload',
12+
'spectrogram_x_stretch',
13+
'spectrogram_view',
14+
)
15+
16+
def has_add_permission(self, request):
17+
# Allow add only if there is no Configuration instance
18+
if Configuration.objects.exists():
19+
return False
20+
return super().has_add_permission(request)
21+
22+
def has_delete_permission(self, request, obj=None):
23+
# Prevent deleting the Configuration through the admin
24+
return False

bats_ai/core/admin/image.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from django.http import HttpRequest
44

55
from bats_ai.core.models import Image
6-
from bats_ai.core.tasks import image_compute_checksum
6+
from bats_ai.tasks.tasks import image_compute_checksum
77

88

99
@admin.register(Image)

bats_ai/core/admin/nabat/admin.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from django.contrib import admin
2+
3+
from bats_ai.core.models.nabat import (
4+
NABatCompressedSpectrogram,
5+
NABatRecording,
6+
NABatRecordingAnnotation,
7+
NABatSpectrogram,
8+
)
9+
10+
11+
# Register models for the NaBat category
12+
@admin.register(NABatRecordingAnnotation)
13+
class NABatRecordingAnnotationAdmin(admin.ModelAdmin):
14+
list_display = (
15+
'nabat_recording',
16+
'comments',
17+
'model',
18+
'confidence',
19+
'additional_data',
20+
'species_codes',
21+
)
22+
search_fields = ('nabat_recording_name', 'comments', 'model')
23+
list_filter = ('nabat_recording',)
24+
25+
@admin.display(description='Species Codes')
26+
def species_codes(self, obj):
27+
# Assuming species have a `species_code` field
28+
return ', '.join([species.species_code for species in obj.species.all()])
29+
30+
31+
@admin.register(NABatSpectrogram)
32+
class NABatSpectrogramAdmin(admin.ModelAdmin):
33+
list_display = (
34+
'nabat_recording',
35+
'image_file',
36+
'width',
37+
'height',
38+
'duration',
39+
'frequency_min',
40+
'frequency_max',
41+
'colormap',
42+
)
43+
search_fields = ('nabat_recording__name', 'colormap')
44+
list_filter = ('nabat_recording', 'colormap')
45+
46+
47+
@admin.register(NABatCompressedSpectrogram)
48+
class NABatCompressedSpectrogramAdmin(admin.ModelAdmin):
49+
list_display = ('nabat_recording', 'spectrogram', 'length', 'cache_invalidated')
50+
search_fields = ('nabat_recording__name', 'spectrogram__id')
51+
list_filter = ('nabat_recording', 'cache_invalidated')
52+
53+
54+
@admin.register(NABatRecording)
55+
class NABatRecordingAdmin(admin.ModelAdmin):
56+
list_display = (
57+
'name',
58+
'recording_id',
59+
'equipment',
60+
'comments',
61+
'recording_location',
62+
'grts_cell_id',
63+
'grts_cell',
64+
)
65+
search_fields = ('name', 'recording_id', 'recording_location')
66+
list_filter = ('name', 'recording_id', 'recording_location')
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from django.contrib import admin
2+
3+
from bats_ai.core.models import ProcessingTask
4+
5+
6+
@admin.register(ProcessingTask)
7+
class ProcessingTaskAdmin(admin.ModelAdmin):
8+
list_display = ('id', 'name', 'status', 'created', 'modified', 'celery_id', 'metadata', 'error')
9+
list_filter = ('status', 'created', 'modified')
10+
search_fields = ('name', 'celery_id', 'metadata', 'error')
11+
ordering = ('-created',)
12+
readonly_fields = ('created', 'modified')
13+
fieldsets = (
14+
(None, {'fields': ('name', 'status', 'celery_id', 'error')}),
15+
(
16+
'Metadata',
17+
{
18+
'classes': ('collapse',),
19+
'fields': ('metadata',),
20+
},
21+
),
22+
(
23+
'Timestamps',
24+
{
25+
'fields': ('created', 'modified'),
26+
},
27+
),
28+
)

bats_ai/core/admin/recording.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from django.utils.safestring import mark_safe
66

77
from bats_ai.core.models import Recording
8-
from bats_ai.core.tasks import recording_compute_spectrogram
8+
from bats_ai.tasks.tasks import recording_compute_spectrogram
99

1010

1111
@admin.register(Recording)

bats_ai/core/management/commands/makeclient.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import os
2+
13
from django.contrib.auth.models import User
24
import djclick as click
35
from oauth2_provider.models import Application
46

5-
CLIENT_ID = 'HSJWFZ2cIpWQOvNyCXyStV9hiOd7DfWeBOCzo4pP'
7+
CLIENT_ID = os.environ.get('APPLICATION_CLIENT_ID', 'HSJWFZ2cIpWQOvNyCXyStV9hiOd7DfWeBOCzo4pP')
68

79

810
# create django oauth toolkit appliction (client)
@@ -12,10 +14,23 @@
1214
required=True,
1315
help='superuser username for application creator',
1416
)
15-
@click.option('--uri', type=click.STRING, required=True, help='redirect uri for application')
17+
@click.option(
18+
'--uri',
19+
type=click.STRING,
20+
default='http://localhost:3000/',
21+
required=False,
22+
help='redirect uri for application',
23+
)
24+
@click.option(
25+
'--clientid',
26+
type=click.STRING,
27+
default=CLIENT_ID,
28+
required=False,
29+
help='clientID used in the application',
30+
)
1631
@click.command()
17-
def command(username, uri):
18-
if Application.objects.filter(client_id=CLIENT_ID).exists():
32+
def command(username, uri, clientid):
33+
if Application.objects.filter(client_id=clientid).exists():
1934
click.echo('The client already exists. You can administer it from the admin console.')
2035
return
2136

@@ -29,7 +44,7 @@ def command(username, uri):
2944
if user:
3045
application = Application(
3146
name='batsai-client',
32-
client_id=CLIENT_ID,
47+
client_id=clientid,
3348
client_secret='',
3449
client_type='public',
3550
redirect_uris=uri,

0 commit comments

Comments
 (0)