Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduces PTP tab and Job #2

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b3fcbb9
Introduce logic image to annotation in Point to Polygon Job
dbrembilla Nov 8, 2024
eddabfc
Initialise PTP script
dbrembilla Nov 11, 2024
e384eba
Add new mock PTP controller, API and Job
dbrembilla Nov 11, 2024
d5f6b36
Make the PTP python script functioning, add docstrings
dbrembilla Nov 12, 2024
f327d51
Add requirements.txt for Python
dbrembilla Nov 12, 2024
38b4dea
Fix PTP job, now able to run the python script
dbrembilla Nov 12, 2024
324bbc3
Apply black formatting to Python script
dbrembilla Nov 12, 2024
f05d894
Sorts imports of Python script
dbrembilla Nov 12, 2024
7d4ede1
Initialse the PTP sidebar
dbrembilla Nov 12, 2024
a88ee9d
Introduce PTP view
dbrembilla Nov 13, 2024
540e09c
Initialise PTP tab, loading point annotations
dbrembilla Nov 15, 2024
6ec484d
Add ptp tab, now showing images
dbrembilla Nov 18, 2024
46269e5
Fix import and main.js for assets from largo
dbrembilla Nov 18, 2024
4afcd80
Introduce images in the Ptp Tab, grouped per labels
dbrembilla Nov 19, 2024
1b985d5
Allow styles to be published via Webpack
dbrembilla Nov 20, 2024
9e44308
Add job spawn route system to frontend, grouped by labels
dbrembilla Nov 20, 2024
99d09f1
Fix logic, output dir in Python script
dbrembilla Nov 25, 2024
5e14200
Introduces UploadPtpJob, jobs can now be started from the frontend
dbrembilla Nov 25, 2024
884bf3d
Add Ptp Expected Area Model
dbrembilla Nov 25, 2024
06c64bc
Remove double code from Python script
dbrembilla Nov 26, 2024
35b0aa2
Refactor Point to Polygon Pipeline
dbrembilla Nov 28, 2024
13d6e00
Introduce UploadConvertedAnnotationsJob
dbrembilla Nov 29, 2024
46db849
Fix ImageAnnotation import bug in Job
dbrembilla Dec 2, 2024
eb8d211
Introduce error message if no label selected in Ptp view
dbrembilla Dec 2, 2024
35ab9cc
Fix bugs within PTP python script
dbrembilla Dec 3, 2024
08bd68d
Introduce update of ImageAnnotationLabels table
dbrembilla Dec 3, 2024
18bba64
Clean up PTP container, improve style
dbrembilla Dec 3, 2024
dd6486c
src/resources/assets/js/api/labelAnnotations.js
dbrembilla Dec 3, 2024
a242820
Remove useless API file
dbrembilla Dec 3, 2024
dd6019b
Clean up PtpContainer component
dbrembilla Dec 3, 2024
a418c5d
Remove useless commit
dbrembilla Dec 3, 2024
4d61d77
Remove commits, add docstrings
dbrembilla Dec 3, 2024
aa0ae07
Remove useless commit
dbrembilla Dec 3, 2024
0012002
Add Publish command to Ptp
dbrembilla Dec 3, 2024
02f8ab9
Try and fix test scripts
dbrembilla Dec 4, 2024
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
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ jobs:
docker pull ghcr.io/biigle/worker:latest

- name: Start test database
run: docker-compose up -d --no-build database_testing && sleep 5
run: docker compose up -d --no-build database_testing && sleep 5
working-directory: ../core

- name: Run tests
run: docker-compose run --rm -u 1001 worker php -d memory_limit=1G vendor/bin/phpunit --random-order --filter 'Biigle\\Tests\\Modules\\'${MODULE_NAME}
run: docker compose run --rm -u 1001 worker php -d memory_limit=1G vendor/bin/phpunit --random-order --filter 'Biigle\\Tests\\Modules\\'${MODULE_NAME}
working-directory: ../core
7 changes: 7 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
torch==2.1.*
git+https://github.com/facebookresearch/segment-anything.git
numpy==1.24.*
Pillow==9.3.*
sahi==0.11.18
shapely==2.0.6
pycocotools==2.0.8
Comment on lines +5 to +7
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last three are not really required, right?

38 changes: 38 additions & 0 deletions src/Console/Commands/Publish.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Biigle\Modules\Ptp\Console\Commands;

use Biigle\Modules\Ptp\PtpServiceProvider as ServiceProvider;
use Illuminate\Console\Command;

class Publish extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'ptp:publish';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Publish or refresh the public assets of this package';

/**
* Execute the command.
*
* @return void
*/
public function handle()
{
$this->call('vendor:publish', [
'--provider' => ServiceProvider::class,
'--tag' => ['public'],
'--force' => true,
]);
}
}

32 changes: 32 additions & 0 deletions src/Database/Factories/PtpExpectedAreaFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Biigle\Modules\Ptp\Database\Factories;

use Biigle\Label;
use Biigle\Modules\Ptp\PtpExpectedArea;
use Biigle\Volume;
use Illuminate\Database\Eloquent\Factories\Factory;

class PtpExpectedAreaFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = PtpExpectedArea::class;

/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'label_id' => Label::factory(),
'volume_id' => Volume::factory(),
'areas' => json_encode([]),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('ptp_expected_areas', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('volume_id')->unsigned()->index();
$table->foreign('volume_id')->references('id')->on('volumes')->onDelete('cascade');
$table->integer('label_id')->unsigned()->index();
$table->foreign('label_id')->references('id')->on('labels')->onDelete('cascade');
$table->jsonb('areas');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('ptp_expected_areas');
}
};
124 changes: 0 additions & 124 deletions src/Http/Controllers/Api/MaiaJobController.php

This file was deleted.

91 changes: 91 additions & 0 deletions src/Http/Controllers/Api/PtpController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace Biigle\Modules\Ptp\Http\Controllers\Api;
use Biigle\Http\Controllers\Api\Controller;
use Biigle\Modules\Ptp\Jobs\PtpJob;
use Biigle\Modules\Ptp\Jobs\UploadPtpExpectedAreaJob;
use Biigle\Modules\Ptp\Jobs\UploadConvertedAnnotationsJob;
use Biigle\Modules\Ptp\PtpExpectedArea;
use Biigle\ImageAnnotation;
use Biigle\Volume;
use Biigle\Label;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Bus;

/**
* Controller used for creating a PTP Job Chain
*/
class PtpController extends Controller
{
/**
* Generate Point to Polygon Job Chain.
* This method generates, based on the request. The jobs generated are first for computing and uploading the expected areas of converted polygons.
* Then, it generates a job for executing the conversion and then upload the new annotations to the DB
*
* @param $request
* @return
*/
public function generatePtpJob(Request $request) {
$this->validate($request, ['label_id' => 'integer', 'volume_id' => 'integer']);
$volume = Volume::findOrFail($request->volume_id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to validate that the volume is an image volume and (maybe) that is does not have tiled images here. Video volumes are not supported.

@dlangenk Would the Python script work with a huge image mosaic?

$this->authorize('edit-in', $volume); Label::findOrFail($request->label_id);
$imageAnnotationArray = [];
$labelId = $request->label_id;
$pointShapeId = 1; //Find annotations with selected label in desired volume
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No hard-coded IDs please 😉

Suggested change
$pointShapeId = 1; //Find annotations with selected label in desired volume
$pointShapeId = Shape::pointId(); //Find annotations with selected label in desired volume

$annotations = ImageAnnotation::join('image_annotation_labels','image_annotations.id', '=', 'image_annotation_labels.annotation_id')
->join('images','image_annotations.image_id', '=','images.id')
->where('image_annotation_labels.label_id', $labelId)
->where('images.volume_id', $volume->id)
->where('image_annotations.shape_id', $pointShapeId)
->select('image_annotations.id as id', 'images.id as image_id', 'image_annotations.points as points','image_annotations.shape_id as shape_id')
->get();
foreach ($annotations as $annotation) {
if (!isset($imageAnnotationArray[$annotation->image_id])) {
$imageAnnotationArray[$annotation->image_id] = [];
}
$imageAnnotationArray[$annotation->image_id][] = [
'annotation_id' => $annotation->id,
'points' => $annotation->points,
'shape' => $annotation->shape_id,
'image' => $annotation->image_id,
'label' => $labelId,
];
};

// INFO: should we batch per small number or annotations? for now, just grouping per
// image IDs

$jobArray = [];
$expectedAreaCount = PtpExpectedArea::where('label_id', $labelId)->where('volume_id', $volume->id)->count('id');

if ($expectedAreaCount == 0){
$expectedAreaJobs = [];
$outputDir = config('ptp.temp_dir').'/compute-area/'.$volume->id.'/'.$labelId;

foreach ($imageAnnotationArray as $imageId => $imageAnnotationValues){
$outputFile = "$outputDir/".$labelId."_"."$imageId.json";
$job = new PtpJob($request->user(), $imageAnnotationValues, 'compute-area', $labelId, $outputFile);
array_push($expectedAreaJobs, $job);
}
array_push($jobArray, Bus::batch($expectedAreaJobs));
$uploadJob = new UploadPtpExpectedAreaJob($outputFile, $volume->id, $labelId);
array_push($jobArray, $uploadJob);
}

$ptpConversionJobs = [];
$outputDir = config('ptp.temp_dir').'/ptp/'.$volume->id.'/'.$labelId;

foreach ($imageAnnotationArray as $imageId => $imageAnnotationValues){
$outputFile = "$outputDir/".$labelId."_"."$imageId.json";
$job = new PtpJob($request->user(), $imageAnnotationValues, 'ptp', $labelId, $outputFile) ;
array_push($ptpConversionJobs, $job);
}
$job = new UploadConvertedAnnotationsJob($outputDir, $request->user());

array_push($jobArray, Bus::batch($ptpConversionJobs), $job);

Bus::chain($jobArray)->dispatch();

return ['submitted' => true];
}
}
Loading
Loading