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
6 changes: 3 additions & 3 deletions ami/exports/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ def create(self, request, *args, **kwargs):
collection = SourceImageCollection.objects.get(pk=collection_id)
except SourceImageCollection.DoesNotExist:
return Response(
{"error": "Collection does not exist."},
{"error": "Capture set does not exist."},
status=status.HTTP_400_BAD_REQUEST,
)
if collection.project != project:
return Response(
{"error": "Collection does not belong to the selected project."},
{"error": "Capture set does not belong to the selected project."},
status=status.HTTP_400_BAD_REQUEST,
)

Expand All @@ -73,7 +73,7 @@ def create(self, request, *args, **kwargs):
data_export.save()
data_export.update_record_count()

job_name = f"Export occurrences{f' for collection {collection.pk}' if collection else ''}"
job_name = f"Export occurrences{f' for capture set {collection.pk}' if collection else ''}"
job = Job.objects.create(
name=job_name,
project=project,
Expand Down
12 changes: 6 additions & 6 deletions ami/jobs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,13 +657,13 @@ def run(cls, job: "Job"):


class SourceImageCollectionPopulateJob(JobType):
name = "Populate captures collection"
name = "Populate capture set"
key = "populate_captures_collection"

@classmethod
def run(cls, job: "Job"):
"""
Run the populate source image collection job.
Run the populate capture set job.

This is meant to be called by an async task, not directly.
"""
Expand All @@ -675,9 +675,9 @@ def run(cls, job: "Job"):
job.save()

if not job.source_image_collection:
raise ValueError("No source image collection provided")
raise ValueError("No capture set provided")

job.logger.info(f"Populating source image collection {job.source_image_collection}")
job.logger.info(f"Populating capture set {job.source_image_collection}")
job.update_status(JobState.STARTED)
job.started_at = datetime.datetime.now()
job.finished_at = None
Expand All @@ -690,11 +690,11 @@ def run(cls, job: "Job"):
job.save()

job.source_image_collection.populate_sample(job=job)
job.logger.info(f"Finished populating source image collection {job.source_image_collection}")
job.logger.info(f"Finished populating capture set {job.source_image_collection}")
job.save()

captures_added = job.source_image_collection.images.count()
job.logger.info(f"Added {captures_added} captures to source image collection {job.source_image_collection}")
job.logger.info(f"Added {captures_added} captures to capture set {job.source_image_collection}")

job.progress.update_stage(
cls.key,
Expand Down
2 changes: 1 addition & 1 deletion ami/jobs/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class JobListSerializer(DefaultSerializer):
source="source_image_single",
)
source_image_collection_id = serializers.PrimaryKeyRelatedField(
label="Source Image Collection",
label="Capture Set",
write_only=True,
required=False,
allow_null=True,
Expand Down
8 changes: 4 additions & 4 deletions ami/main/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,22 +638,22 @@ def image_count(self, obj) -> int:
def populate_collection(self, request: HttpRequest, queryset: QuerySet[SourceImageCollection]) -> None:
for collection in queryset:
collection.populate_sample()
self.message_user(request, f"Populated {queryset.count()} collection(s).")
self.message_user(request, f"Populated {queryset.count()} capture set(s).")

@admin.action()
def populate_collection_async(self, request: HttpRequest, queryset: QuerySet[SourceImageCollection]) -> None:
queued_tasks = [tasks.populate_collection.apply_async([collection.pk]) for collection in queryset]
self.message_user(
request,
f"Populating {len(queued_tasks)} collection(s) background tasks: {queued_tasks}.",
f"Populating {len(queued_tasks)} capture set(s) background tasks: {queued_tasks}.",
)

@admin.action(description="Run Small Size Filter post-processing task (async)")
def run_small_size_filter(self, request: HttpRequest, queryset: QuerySet[SourceImageCollection]) -> None:
jobs = []
for collection in queryset:
job = Job.objects.create(
name=f"Post-processing: SmallSizeFilter on Collection {collection.pk}",
name=f"Post-processing: SmallSizeFilter on Capture Set {collection.pk}",
project=collection.project,
job_type_key="post_processing",
params={
Expand All @@ -666,7 +666,7 @@ def run_small_size_filter(self, request: HttpRequest, queryset: QuerySet[SourceI
job.enqueue()
jobs.append(job.pk)

self.message_user(request, f"Queued Small Size Filter for {queryset.count()} collection(s). Jobs: {jobs}")
self.message_user(request, f"Queued Small Size Filter for {queryset.count()} capture set(s). Jobs: {jobs}")

actions = [
populate_collection,
Expand Down
26 changes: 13 additions & 13 deletions ami/main/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ def add_adjacent_captures(self, queryset: QuerySet) -> QuerySet:
@action(detail=True, methods=["post"], name="star")
def star(self, _request, pk=None) -> Response:
"""
Add a source image to the project's starred images collection.
Add a capture to the project's starred images capture set.
"""
source_image: SourceImage = self.get_object()
if source_image and source_image.deployment and source_image.deployment.project:
Expand All @@ -694,7 +694,7 @@ def star(self, _request, pk=None) -> Response:
@action(detail=True, methods=["post"], name="unstar")
def unstar(self, _request, pk=None) -> Response:
"""
Remove a source image from the project's starred images collection.
Remove a capture from the project's starred images capture set.
"""
source_image: SourceImage = self.get_object()
if source_image and source_image.deployment and source_image.deployment.project:
Expand All @@ -707,7 +707,7 @@ def unstar(self, _request, pk=None) -> Response:

class SourceImageCollectionViewSet(DefaultViewSet, ProjectMixin):
"""
Endpoint for viewing collections or samples of source images.
Endpoint for viewing capture sets or samples of captures.
"""

queryset = (
Expand Down Expand Up @@ -766,26 +766,26 @@ def get_queryset(self) -> QuerySet:
@action(detail=True, methods=["post"], name="populate")
def populate(self, request, pk=None):
"""
Populate a collection with source images using the configured sampling method and arguments.
Populate a capture set with captures using the configured sampling method and arguments.
"""
collection: SourceImageCollection = self.get_object()

if collection:
from ami.jobs.models import Job, SourceImageCollectionPopulateJob

assert collection.project, "Collection must be associated with a project"
assert collection.project, "Capture set must be associated with a project"
job = Job.objects.create(
name=f"Populate captures for collection {collection.pk}",
name=f"Populate captures for capture set {collection.pk}",
project=collection.project,
source_image_collection=collection,
job_type_key=SourceImageCollectionPopulateJob.key,
)
job.enqueue()
msg = f"Populating captures for collection {collection.pk} in background."
msg = f"Populating captures for capture set {collection.pk} in background."
logger.info(msg)
return Response({"job_id": job.pk, "project_id": collection.project.pk})
else:
raise api_exceptions.ValidationError(detail="Invalid collection requested")
raise api_exceptions.ValidationError(detail="Invalid capture set requested")

def _get_source_image(self):
"""
Expand All @@ -812,7 +812,7 @@ def _serialize_source_image(self, source_image):
@action(detail=True, methods=["post"], name="add")
def add(self, request, pk=None):
"""
Add a source image to a collection.
Add a capture to a capture set.
"""
collection: SourceImageCollection = self.get_object()
source_image = self._get_source_image()
Expand All @@ -828,7 +828,7 @@ def add(self, request, pk=None):
@action(detail=True, methods=["post"], name="remove")
def remove(self, request, pk=None):
"""
Remove a source image from a collection.
Remove a capture from a capture set.
"""
collection = self.get_object()
source_image = self._get_source_image()
Expand Down Expand Up @@ -991,7 +991,7 @@ def filter_queryset(self, request, queryset, view):

class OccurrenceCollectionFilter(filters.BaseFilterBackend):
"""
Filter occurrences by the collection their detections source images belong to.
Filter occurrences by the capture set their detections' captures belong to.
"""

query_params = ["collection_id", "collection"] # @TODO remove "collection" param when UI is updated
Expand Down Expand Up @@ -1158,7 +1158,7 @@ def filter_queryset(self, request, queryset, view):

class TaxonCollectionFilter(filters.BaseFilterBackend):
"""
Filter taxa by the collection their occurrences belong to.
Filter taxa by the capture set their occurrences belong to.
"""

query_param = "collection"
Expand Down Expand Up @@ -1260,7 +1260,7 @@ def get_queryset(self) -> QuerySet["Occurrence"]:
),
OpenApiParameter(
name="collection_id",
description="Filter occurrences by the collection their detections' source images belong to.",
description="Filter occurrences by the capture set their detections' captures belong to.",
required=False,
type=OpenApiTypes.INT,
),
Expand Down
2 changes: 1 addition & 1 deletion ami/main/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def get_or_create_default_collection(project: "Project") -> "SourceImageCollecti
project=project,
method="full",
)
logger.info(f"Created default collection for project {project}")
logger.info(f"Created default capture set for project {project}")
return collection


Expand Down
26 changes: 14 additions & 12 deletions ami/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,28 @@ def write_tasks(label_studio_config_id: int) -> int:
def populate_collection(collection_id: int) -> None:
from ami.main.models import SourceImageCollection

collection = SourceImageCollection.objects.get(id=collection_id)
if collection:
logger.info(f"Populating collection {collection}")
collection.populate_sample()
else:
logger.error(f"SourceImageCollection with id {collection_id} not found")
try:
collection = SourceImageCollection.objects.get(id=collection_id)
except SourceImageCollection.DoesNotExist:
logger.error(f"Capture set with id {collection_id} not found")
return
logger.info(f"Populating capture set {collection}")
collection.populate_sample()


# Task to group images into events
@celery_app.task(soft_time_limit=one_hour, time_limit=one_hour + 60)
def regroup_events(deployment_id: int) -> None:
from ami.main.models import Deployment, group_images_into_events

deployment = Deployment.objects.get(id=deployment_id)
if deployment:
logger.info(f"Grouping captures for {deployment}")
events = group_images_into_events(deployment)
logger.info(f"{deployment } now has {len(events)} events")
else:
try:
deployment = Deployment.objects.get(id=deployment_id)
except Deployment.DoesNotExist:
logger.error(f"Deployment with id {deployment_id} not found")
return
logger.info(f"Grouping captures for {deployment}")
events = group_images_into_events(deployment)
logger.info(f"{deployment} now has {len(events)} events")


@celery_app.task(soft_time_limit=one_hour, time_limit=one_hour + 60)
Expand Down
Loading