Skip to content

Commit

Permalink
Merge branch 'master' into flat-label-list-tab
Browse files Browse the repository at this point in the history
  • Loading branch information
mzur committed Jan 30, 2025
2 parents 47795de + fc7ad73 commit 84f2fe7
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 60 deletions.
31 changes: 23 additions & 8 deletions src/Http/Requests/StoreLargoSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,18 @@ protected function getAffectedAnnotations($dismissed, $changed)
*/
protected function imageAnotationsBelongToVolumes($annotations, $volumes)
{
return !ImageAnnotation::join('images', 'image_annotations.image_id', '=', 'images.id')
->whereIn('image_annotations.id', $annotations)
->whereNotIn('images.volume_id', $volumes)
->exists();
$chunkedAnnotations = array_chunk($annotations,config('biigle.db_param_limit') - count($volumes));
foreach($chunkedAnnotations as $chunkedAnnotation){
$queryReturn = ImageAnnotation::join('images', 'image_annotations.image_id', '=', 'images.id')
->whereIn('image_annotations.id', $chunkedAnnotation)
->whereNotIn('images.volume_id', $volumes)
->exists();
if ($queryReturn){
return false;
}
}
return true;

}

/**
Expand All @@ -128,10 +136,17 @@ protected function imageAnotationsBelongToVolumes($annotations, $volumes)
*/
protected function videoAnotationsBelongToVolumes($annotations, $volumes)
{
return !VideoAnnotation::join('videos', 'video_annotations.video_id', '=', 'videos.id')
->whereIn('video_annotations.id', $annotations)
->whereNotIn('videos.volume_id', $volumes)
->exists();
$chunkedAnnotations = array_chunk($annotations,config('biigle.db_param_limit') - count($volumes));
foreach($chunkedAnnotations as $chunkedAnnotation){
$queryReturn = VideoAnnotation::join('videos', 'video_annotations.video_id', '=', 'videos.id')
->whereIn('video_annotations.id', $chunkedAnnotation)
->whereNotIn('videos.volume_id', $volumes)
->exists();
if ($queryReturn){
return false;
}
}
return true;
}

/**
Expand Down
30 changes: 22 additions & 8 deletions src/Http/Requests/StoreProjectLargoSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,17 @@ public function withValidator($validator)
*/
protected function getAffectedImageVolumes($annotations)
{
return ImageAnnotation::join('images', 'image_annotations.image_id', '=', 'images.id')
->whereIn('image_annotations.id', $annotations)
->distinct()
->pluck('images.volume_id');
$chunkedAnnotations = array_chunk($annotations,config('biigle.db_param_limit'));
$volumeIdsArray = [];
foreach($chunkedAnnotations as $chunkedAnnotation){
$chunkVolumeId = ImageAnnotation::join('images', 'image_annotations.image_id', '=', 'images.id')
->whereIn('image_annotations.id', $chunkedAnnotation)
->distinct()
->pluck('images.volume_id')
->toArray();
$volumeIdsArray = array_merge($volumeIdsArray, $chunkVolumeId);
}
return array_unique($volumeIdsArray);
}

/**
Expand All @@ -136,9 +143,16 @@ protected function getAffectedImageVolumes($annotations)
*/
protected function getAffectedVideoVolumes($annotations)
{
return VideoAnnotation::join('videos', 'video_annotations.video_id', '=', 'videos.id')
->whereIn('video_annotations.id', $annotations)
->distinct()
->pluck('videos.volume_id');
$chunkedAnnotations = array_chunk($annotations,config('biigle.db_param_limit'));
$volumeIdsArray = [];
foreach($chunkedAnnotations as $chunkedAnnotation){
$chunkVolumeId = VideoAnnotation::join('videos', 'video_annotations.video_id', '=', 'videos.id')
->whereIn('video_annotations.id', $chunkedAnnotation)
->distinct()
->pluck('videos.volume_id')
->toArray();
$volumeIdsArray = array_merge($volumeIdsArray, $chunkVolumeId);
}
return array_unique($volumeIdsArray);
}
}
51 changes: 35 additions & 16 deletions src/Jobs/ApplyLargoSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use DB;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Throwable;

class ApplyLargoSession extends Job implements ShouldQueue
{
Expand Down Expand Up @@ -120,23 +121,41 @@ public function __construct($id, User $user, $dismissedImageAnnotations, $change
*/
public function handle()
{
try {
DB::transaction(function () {
$this->handleImageAnnotations();
$this->handleVideoAnnotations();
});

LargoSessionSaved::dispatch($this->id, $this->user);
} catch (\Exception $e) {
LargoSessionFailed::dispatch($this->id, $this->user);
} finally {
Volume::where('attrs->largo_job_id', $this->id)->each(function ($volume) {
$attrs = $volume->attrs;
unset($attrs['largo_job_id']);
$volume->attrs = $attrs;
$volume->save();
});
if (!Volume::where('attrs->largo_job_id', $this->id)->exists()) {
// The job previously exited or failed. Don't run it twice.
// This can happen if the admin reruns failed jobs.
return;
}

DB::transaction(function () {
$this->handleImageAnnotations();
$this->handleVideoAnnotations();
});

$this->cleanupJobId();
LargoSessionSaved::dispatch($this->id, $this->user);
}

/**
* Handle a job failure.
*/
public function failed(?Throwable $exception): void
{
$this->cleanupJobId();
LargoSessionFailed::dispatch($this->id, $this->user);
}

/**
* Remove the properties that indicate that a save Largo session is in progress.
*/
protected function cleanupJobId(): void
{
Volume::where('attrs->largo_job_id', $this->id)->each(function ($volume) {
$attrs = $volume->attrs;
unset($attrs['largo_job_id']);
$volume->attrs = $attrs;
$volume->save();
});
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/public/assets/scripts/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/public/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"/assets/scripts/main.js": "/assets/scripts/main.js?id=fb79978afc6a6d9745dd1e6ea7320e8f",
"/assets/scripts/main.js": "/assets/scripts/main.js?id=e1053b7af4d2947420a8f46c4fa630c8",
"/assets/styles/main.css": "/assets/styles/main.css?id=0ef4b3ef391cbeaff5022f2ba61a6b05"
}
9 changes: 9 additions & 0 deletions src/resources/assets/js/components/settingsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<script>
import Settings from '../stores/settings';
import {PowerToggle} from '../import';
import { Keyboard } from '../import';
export default {
components: {
Expand Down Expand Up @@ -51,6 +52,14 @@ export default {
this.restoreKeys.forEach((key) => {
this[key] = this.settings.get(key);
});
Keyboard.on('o', () => {
if (this.showOutlines) {
this.disableOutlines();
} else {
this.enableOutlines();
}
});
},
};
</script>
Expand Down
1 change: 1 addition & 0 deletions src/resources/assets/js/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export let Settings = biigle.$require('core.models.Settings');
export let SettingsTabPlugins = biigle.$require('annotations.components.settingsTabPlugins');
export let Sidebar = biigle.$require('core.components.sidebar');
export let SidebarTab = biigle.$require('core.components.sidebarTab');
export let Keyboard = biigle.$require('core.keyboard');
3 changes: 1 addition & 2 deletions src/resources/assets/js/mixins/largoContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ export default {
return annotations;
}
// This will be empty for the default sorting.
if (this.sortingSequence.length > 0) {
if (this.sortingKey !== SORT_KEY.ANNOTATION_ID) {
const map = {};
annotations.forEach((a) => {
// Image annotation IDs are prefixed with 'i', video annotations with
Expand Down
2 changes: 1 addition & 1 deletion src/resources/views/manual/tutorials/largo.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@

<dl>
<dt>Show annotation outlines</dt>
<dd>Disable this option to hide the outlines of the annotation on each patch (enabled by default).</dd>
<dd>Disable this option to hide the outlines of the annotation on each patch (enabled by default). Use the <kbd>o</kbd> key as shortcut.</dd>
</dl>

<h3><a name="example-use-cases"></a>Example use cases</h3>
Expand Down
61 changes: 61 additions & 0 deletions tests/Http/Controllers/Api/Projects/LargoControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use ApiTestCase;
use Biigle\MediaType;
use Biigle\ImageAnnotation;
use Biigle\VideoAnnotation;
use Biigle\Label;
use Biigle\Modules\Largo\Jobs\ApplyLargoSession;
use Biigle\Modules\Largo\Jobs\RemoveImageAnnotationPatches;
use Biigle\Modules\Largo\Jobs\RemoveVideoAnnotationPatches;
Expand Down Expand Up @@ -443,4 +446,62 @@ public function testStoreJobStillRunningVideoAnnotations()
'changed_video_annotations' => [],
])->assertStatus(422);
}

public function testChunkingImgProject()
{
config(['biigle.db_param_limit' => 2]);
$image = ImageTest::create(['volume_id' => $this->imageVolume->id,
'filename' => "testImage"]);

$imageAnnotations = ImageAnnotation::factory()->count(5)->create(['image_id' => $image->id]);
$label = Label::factory()->create();


$imageAnnotations->each(fn($imageAnnotation) =>
ImageAnnotationLabelTest::create([
'annotation_id' => $imageAnnotation->id,
'user_id' => $this->editor()->id,
'label_id' => $label->id,
]));


$this->beEditor();
$this->postJson("/api/v1/projects/{$this->project()->id}/largo", [
'dismissed_image_annotations' => [
$this->imageAnnotationLabel->label_id => $imageAnnotations->pluck('id'),
],
'changed_image_annotations' => [],
])
->assertStatus(200);
Queue::assertPushed(ApplyLargoSession::class);
}

public function testChunkingVidProject()
{
config(['biigle.db_param_limit' => 2]);
$video = VideoTest::create(['volume_id' => $this->videoVolume->id,
'filename' => "testVideo"]);
$videoAnnotations = VideoAnnotation::factory()->count(5)->create(['video_id' => $video->id]);

$label = Label::factory()->create();

$videoAnnotations->each(fn($videoAnnotation) =>
VideoAnnotationLabelTest::create([
'annotation_id' => $videoAnnotation->id,
'user_id' => $this->editor()->id,
'label_id' => $label->id,
]));


$this->beEditor();
$this->postJson("/api/v1/projects/{$this->project()->id}/largo", [
'dismissed_video_annotations' => [
$this->videoAnnotationLabel->label_id => $videoAnnotations->pluck('id'),
],
'changed_video_annotations' => [],
])
->assertStatus(200);
Queue::assertPushed(ApplyLargoSession::class);
}

}
62 changes: 62 additions & 0 deletions tests/Http/Controllers/Api/Volumes/LargoControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use ApiTestCase;
use Biigle\MediaType;
use Biigle\ImageAnnotation;
use Biigle\VideoAnnotation;
use Biigle\Label;
use Biigle\Modules\Largo\Jobs\ApplyLargoSession;
use Biigle\Modules\Largo\Jobs\RemoveImageAnnotationPatches;
use Biigle\Modules\Largo\Jobs\RemoveVideoAnnotationPatches;
Expand Down Expand Up @@ -439,4 +442,63 @@ public function testStoreJobStillRunningVideoAnnotations()
'changed_video_annotations' => [],
])->assertStatus(422);
}


public function testChunkingImgVol()
{
config(['biigle.db_param_limit' => 2]);
$image = ImageTest::create(['volume_id' => $this->imageVolume->id,
'filename' => "testImage"]);

$imageAnnotations = ImageAnnotation::factory()->count(5)->create(['image_id' => $image->id]);
$label = Label::factory()->create();


$imageAnnotations->each(fn($imageAnnotation) =>
ImageAnnotationLabelTest::create([
'annotation_id' => $imageAnnotation->id,
'user_id' => $this->editor()->id,
'label_id' => $label->id,
]));


$this->beEditor();
$this->postJson("/api/v1/volumes/{$this->imageVolume->id}/largo", [
'dismissed_image_annotations' => [
$this->imageAnnotationLabel->label_id => $imageAnnotations->pluck('id'),
],
'changed_image_annotations' => [],
])
->assertStatus(200);
Queue::assertPushed(ApplyLargoSession::class);
}

public function testChunkingVidVol()
{
config(['biigle.db_param_limit' => 2]);
$video = VideoTest::create(['volume_id' => $this->videoVolume->id,
'filename' => "testVideo"]);
$videoAnnotations = VideoAnnotation::factory()->count(5)->create(['video_id' => $video->id]);

$label = Label::factory()->create();

$videoAnnotations->each(function($videoAnnotation) use($label){
VideoAnnotationLabelTest::create([
'annotation_id' => $videoAnnotation->id,
'user_id' => $this->editor()->id,
'label_id' => $label->id,
]);
});


$this->beEditor();
$this->postJson("/api/v1/volumes/{$this->videoVolume->id}/largo", [
'dismissed_video_annotations' => [
$this->videoAnnotationLabel->label_id => $videoAnnotations->pluck('id'),
],
'changed_video_annotations' => [],
])
->assertStatus(200);
Queue::assertPushed(ApplyLargoSession::class);
}
}
Loading

0 comments on commit 84f2fe7

Please sign in to comment.