Skip to content
Open
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
8 changes: 6 additions & 2 deletions app/Console/Commands/MapOrganismNamesToOGG.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function handle()
} else {
$data = $this->getOLSIRI(explode(' ', $name)[0], 'family');
if ($data) {
$this->updateOrganismModel($name, $data, $organism, 'genus');
$this->updateOrganismModel($name, $data, $organism, 'family');
$this->info("Mapped and updated: $name");
} else {
$this->getGNFMatches($name, $organism);
Expand Down Expand Up @@ -155,7 +155,7 @@ protected function getOLSIRI($name, $rank)
if (isset($data['elements']) && count($data['elements']) > 0) {

$element = $data['elements'][0];
if (isset($element['iri'], $element['ontologyId']) && $element['isObsolete'] === 'false') {
if (isset($element['iri'], $element['ontologyId']) && $element['isObsolete'] === false) {
if ($rank && $rank == 'species') {
if (isset($element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank']) && $element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank'] == 'http://purl.obolibrary.org/obo/NCBITaxon_species') {
return urlencode($element['iri']);
Expand Down Expand Up @@ -188,6 +188,10 @@ protected function updateOrganismModel($name, $iri, $organism = null, $rank = nu
if ($organism) {
$organism->iri = $iri;
$organism->rank = $rank;
// Auto-generate slug if not exists
if (! $organism->slug) {
$organism->slug = \Illuminate\Support\Str::slug($name);
}
$organism->save();
} else {
$this->error("Organism not found in the database: $name");
Expand Down
111 changes: 52 additions & 59 deletions app/Filament/Dashboard/Resources/OrganismResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,13 @@
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Components\Group;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use GuzzleHttp\Client;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
Expand All @@ -46,30 +43,19 @@ public static function form(Schema $schema): Schema
{
return $schema
->components([
Grid::make()
Section::make('Organism Information')
->description('Enter the organism details below')
->schema(Organism::getForm()),

Section::make('Similar Organisms')
->description('View similar organisms in the database')
->schema([
Group::make()
->schema([
Section::make('')
->schema(Organism::getForm()),
])
->columnSpan(1),
Group::make()
->schema([
Section::make('')
->schema([
OrganismsTable::make('Custom Table'),
// \Livewire\Livewire::mount('similar-organisms', ['organismId' => function ($get) {
// return $get('name');
// }]),
]),
])
->hidden(function ($operation) {
return $operation === 'create';
})
->columnSpan(1),
OrganismsTable::make('Custom Table'),
])
->columns(2), // Defines the number of columns in the grid
->hidden(function ($operation) {
return $operation === 'create';
})
->collapsible(),
]);
}

Expand All @@ -78,9 +64,13 @@ public static function table(Table $table): Table
return $table
->columns([
TextColumn::make('name')
->searchable(),
->searchable()
->description(fn (Organism $record): ?string => $record->iri ? urldecode($record->iri) : null),
TextColumn::make('rank')->wrap()
->searchable(),
TextColumn::make('molecule_count')
->label('Molecules')
->sortable(),
TextColumn::make('created_at')
->dateTime()
->sortable()
Expand All @@ -101,15 +91,19 @@ public static function table(Table $table): Table
->color('info')
->icon('heroicon-o-link')
->iconButton(),
// Tables\Actions\ViewAction::make(),
ViewAction::make()
->iconButton(),
EditAction::make()
->iconButton(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
])
->recordUrl(
fn (Organism $record): string => self::getUrl('view', ['record' => $record]),
);
}

public static function getRelations(): array
Expand All @@ -129,7 +123,7 @@ public static function getPages(): array
'index' => ListOrganisms::route('/'),
'create' => CreateOrganism::route('/create'),
'edit' => EditOrganism::route('/{record}/edit'),
// 'view' => Pages\ViewOrganism::route('/{record}'),
'view' => Pages\ViewOrganism::route('/{record}'),
];
}

Expand Down Expand Up @@ -219,6 +213,10 @@ protected static function updateOrganismModel($name, $iri, $organism = null, $ra
$organism->name = $name;
$organism->iri = $iri;
$organism->rank = $rank;
// Auto-generate slug if not exists
if (! $organism->slug) {
$organism->slug = \Illuminate\Support\Str::slug($name);
}
$organism->save();
} else {
Log::error("Organism not found in the database: $name");
Expand All @@ -228,46 +226,41 @@ protected static function updateOrganismModel($name, $iri, $organism = null, $ra
protected static function getOLSIRI($name, $rank)
{
$client = new Client([
'base_uri' => 'https://www.ebi.ac.uk/ols4/api/',
'base_uri' => 'https://www.ebi.ac.uk/ols4/api/v2/',
]);

try {
$response = $client->get('search', [
$response = $client->get('entities', [
'query' => [
'q' => $name,
'ontology' => ['ncbitaxon', 'efo', 'obi', 'uberon', 'taxrank'],
'exact' => false,
'obsoletes' => false,
'format' => 'json',
'search' => $name,
'ontologyId' => 'ncbitaxon',
'exactMatch' => true,
'type' => 'class',
],
]);

$data = json_decode($response->getBody(), true);

return $data;
// var_dump($data);

// if (isset($data['elements']) && count($data['elements']) > 0) {
if (isset($data['elements']) && count($data['elements']) > 0) {

// $element = $data['elements'][0];
// if (isset($element['iri'], $element['ontologyId']) && $element['isObsolete'] === 'false') {
// if ($rank && $rank == 'species') {
// if (isset($element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank']) && $element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank'] == 'http://purl.obolibrary.org/obo/NCBITaxon_species') {
// return urlencode($element['iri']);
// }
// } elseif ($rank && $rank == 'genus') {
// if (isset($element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank']) && $element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank'] == 'http://purl.obolibrary.org/obo/NCBITaxon_genus') {
// return urlencode($element['iri']);
// }
// } elseif ($rank && $rank == 'family') {
// if (isset($element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank']) && $element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank'] == 'http://purl.obolibrary.org/obo/NCBITaxon_family') {
// return urlencode($element['iri']);
// }
// }
// }
// }
$element = $data['elements'][0];
if (isset($element['iri'], $element['ontologyId']) && $element['isObsolete'] === false) {
if ($rank && $rank == 'species') {
if (isset($element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank']) && $element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank'] == 'http://purl.obolibrary.org/obo/NCBITaxon_species') {
return urlencode($element['iri']);
}
} elseif ($rank && $rank == 'genus') {
if (isset($element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank']) && $element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank'] == 'http://purl.obolibrary.org/obo/NCBITaxon_genus') {
return urlencode($element['iri']);
}
} elseif ($rank && $rank == 'family') {
if (isset($element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank']) && $element['http://purl.obolibrary.org/obo/ncbitaxon#has_rank'] == 'http://purl.obolibrary.org/obo/NCBITaxon_family') {
return urlencode($element['iri']);
}
}
}
}
} catch (Exception $e) {
// Self::error("Error fetching IRI for $name: " . $e->getMessage());
Log::error("Error fetching IRI for $name: ".$e->getMessage());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@
class CreateOrganism extends CreateRecord
{
protected static string $resource = OrganismResource::class;

public function getMaxContentWidth(): ?string
{
return 'full';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
namespace App\Filament\Dashboard\Resources\OrganismResource\Pages;

use App\Filament\Dashboard\Resources\OrganismResource;
use App\Models\Organism;
use Filament\Actions\DeleteAction;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
use Illuminate\Support\Facades\DB;

class EditOrganism extends EditRecord
{
Expand All @@ -16,4 +19,123 @@ protected function getHeaderActions(): array
DeleteAction::make(),
];
}

public function getMaxContentWidth(): ?string
{
return 'full';
}

/**
* Merge current organism into target organism
*/
public function mergeOrganism(int $targetId): void
{
$this->executeMerge($targetId);
}

/**
* Execute the merge operation
*/
protected function executeMerge(int $targetOrganismId): void
{
$currentOrganism = $this->record;
$targetOrganism = Organism::findOrFail($targetOrganismId);

if ($currentOrganism->id === $targetOrganismId) {
Notification::make()
->title('Cannot merge organism into itself')
->danger()
->send();

return;
}

DB::beginTransaction();

try {
// Get all molecule_organism records for the current organism
$currentRelations = DB::table('molecule_organism')
->where('organism_id', $currentOrganism->id)
->get();

$transferred = 0;
$skipped = 0;

foreach ($currentRelations as $relation) {
// Check if this exact combination already exists for the target organism
$exists = DB::table('molecule_organism')
->where('organism_id', $targetOrganismId)
->where('molecule_id', $relation->molecule_id)
->where(function ($query) use ($relation) {
$query->where('sample_location_id', $relation->sample_location_id)
->orWhere(function ($q) use ($relation) {
$q->whereNull('sample_location_id')
->where(DB::raw('1'), $relation->sample_location_id === null ? 1 : 0);
});
})
->where(function ($query) use ($relation) {
$query->where('geo_location_id', $relation->geo_location_id)
->orWhere(function ($q) use ($relation) {
$q->whereNull('geo_location_id')
->where(DB::raw('1'), $relation->geo_location_id === null ? 1 : 0);
});
})
->where(function ($query) use ($relation) {
$query->where('ecosystem_id', $relation->ecosystem_id)
->orWhere(function ($q) use ($relation) {
$q->whereNull('ecosystem_id')
->where(DB::raw('1'), $relation->ecosystem_id === null ? 1 : 0);
});
})
->exists();

if (! $exists) {
// Update the record to point to the target organism
DB::table('molecule_organism')
->where('id', $relation->id)
->update(['organism_id' => $targetOrganismId]);
$transferred++;
} else {
// Delete the duplicate record from current organism
DB::table('molecule_organism')
->where('id', $relation->id)
->delete();
$skipped++;
}
}

// Update molecule counts for both organisms
$currentOrganism->molecule_count = DB::table('molecule_organism')
->where('organism_id', $currentOrganism->id)
->distinct('molecule_id')
->count('molecule_id');
$currentOrganism->save();

$targetOrganism->molecule_count = DB::table('molecule_organism')
->where('organism_id', $targetOrganismId)
->distinct('molecule_id')
->count('molecule_id');
$targetOrganism->save();

DB::commit();

Notification::make()
->title('Organisms merged successfully')
->body("Transferred {$transferred} molecule relations to \"{$targetOrganism->name}\". {$skipped} duplicates were skipped.")
->success()
->send();

// Redirect to the target organism's edit page
$this->redirect(OrganismResource::getUrl('edit', ['record' => $targetOrganism]));

} catch (\Exception $e) {
DB::rollBack();

Notification::make()
->title('Merge failed')
->body($e->getMessage())
->danger()
->send();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,20 @@
->badge((string) Organism::query()->where('molecule_count', '>', 0)->count())
->preserveAll()
->default(),
'inactive entries' => PresetView::make()
'inactive' => PresetView::make()
->modifyQueryUsing(fn ($query) => $query->where('molecule_count', '<=', 0))
->favorite()
->badge((string) Organism::query()->where('molecule_count', '<=', 0)->count())
->preserveAll(),
'unmapped' => PresetView::make()
->modifyQueryUsing(fn ($query) => $query->where(function ($q) {
$q->whereNull('rank')->orWhere('rank', '');
}))
->favorite()
->badge(Organism::query()->where(function ($q) {

Check failure on line 44 in app/Filament/Dashboard/Resources/OrganismResource/Pages/ListOrganisms.php

View workflow job for this annotation

GitHub Actions / PHPStan Analysis / PHPStan Analysis (Level 5)

Parameter #1 $badge of method Archilex\AdvancedTables\Components\PresetView::badge() expects Closure|string|null, int<0, max> given.
$q->whereNull('rank')->orWhere('rank', '');
})->count())
->preserveAll(),
];
}
}
Loading
Loading