Skip to content

Commit

Permalink
feat: various ux/ui updates and other minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
CS76 committed May 29, 2024
1 parent 97f9acb commit 822760b
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 37 deletions.
65 changes: 65 additions & 0 deletions app/Console/Commands/ExtractCAS.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace App\Console\Commands;

use App\Models\Molecule;
use DB;
use Illuminate\Console\Command;

class ExtractCAS extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:extract-cas';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';

/**
* Execute the console command.
*/
public function handle()
{
Molecule::whereNull('cas')->whereNotNull('synonyms')->select('id', 'synonyms')->chunk(10000, function ($mols) {
$data = [];
$pattern = "/\b[1-9][0-9]{1,5}-\d{2}-\d\b/";
foreach ($mols as $mol) {
$casIds = preg_grep($pattern, $mol->synonyms);
array_push($data, [
'id' => $mol->id,
'cas' => array_values($casIds),
]);
$this->info("Mapped and updated: $mol->id");
}
$this->insertBatch($data);
});
}

/**
* Insert a batch of data into the database.
*
* @return void
*/
private function insertBatch(array $data)
{
DB::transaction(function () use ($data) {
foreach ($data as $row) {
Molecule::updateorCreate(
[
'id' => $row['id'],
],
[
'cas' => $row['cas'],
]
);
}
});
}
}
107 changes: 107 additions & 0 deletions app/Console/Commands/GenerateAnnotationScore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace App\Console\Commands;

use App\Models\Molecule;
use DB;
use Illuminate\Console\Command;

class GenerateAnnotationScore extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:generate-score';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';

public function handle()
{
$batchSize = 1000;
$offset = 0;

while (true) {
$molecules = DB::table('molecules')
->offset($offset)
->limit($batchSize)
->get();

if ($molecules->isEmpty()) {
break;
}

$data = [];

foreach ($molecules as $molecule) {
$score = $this->calculateAnnotationScore($molecule);
array_push($data, [
'id' => $molecule->id,
'annotation_level' => $score,
]);
}

$this->insertBatch($data);

$offset += $batchSize;
$this->info("Processed batch starting from offset $offset");
}

$this->info('Annotation scores generated successfully.');
}

/**
* Insert a batch of data into the database.
*
* @return void
*/
private function insertBatch(array $data)
{
DB::transaction(function () use ($data) {
foreach ($data as $row) {
Molecule::updateorCreate(
[
'id' => $row['id'],
],
[
'annotation_level' => $row['annotation_level'],
]
);
}
});
}

protected function calculateAnnotationScore($molecule)
{
$literatureCount = DB::table('citables')
->where('citable_id', $molecule->id)
->where('citable_type', 'App\Models\Molecule')
->count();

$organismCount = DB::table('molecule_organism')
->where('molecule_id', $molecule->id)
->count();

$casScore = $molecule->cas ? 1 : 0.5;
$synonymsScore = $molecule->synonyms ? (count(explode(',', $molecule->synonyms)) >= 3 ? 1 : 0.5) : 0;
$nameScore = $molecule->name ? 1 : 0.5;

$literatureScore = $literatureCount >= 3 ? 1 : ($literatureCount >= 1 ? 0.5 : 0);
$organismScore = $organismCount >= 1 ? 1 : 0;

$totalScore = ($literatureScore * 0.30) +
($organismScore * 0.25) +
($casScore * 0.20) +
($synonymsScore * 0.15) +
($nameScore * 0.10);
$finalScore = round($totalScore * 5, 2);

return ceil($finalScore);
}
}
3 changes: 2 additions & 1 deletion app/Http/Controllers/API/SearchController.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ public function search(Request $request)
'select id, COUNT(*) OVER () from mols limit '.
$limit.
' offset '.
$offset;
$offset.
'ORDER BY annotation_level DESC';
}
}
if ($statement) {
Expand Down
2 changes: 1 addition & 1 deletion app/Livewire/RecentMolecules.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function render()
{
return view('livewire.recent-molecules', [
'molecules' => Cache::rememberForever('molecules.recent', function () {
return MoleculeResource::collection(Molecule::where('has_variants', true)->where('name', '!=', null)->orderByDesc('updated_at')->paginate($this->size));
return MoleculeResource::collection(Molecule::where('has_variants', true)->where('name', '!=', null)->where('annotation_level', '=', 5)->orderByDesc('updated_at')->paginate($this->size));
}),
]);
}
Expand Down
2 changes: 1 addition & 1 deletion app/Livewire/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ public function render()
$offset;
} else {
$statement =
'select id, COUNT(*) OVER () from mols limit '.
'select id, COUNT(*) OVER () from molecules ORDER BY annotation_level DESC limit '.
$this->size.
' offset '.
$offset;
Expand Down
3 changes: 3 additions & 0 deletions resources/views/livewire/header.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray
</button>
</div>
<div class="hidden lg:flex lg:gap-x-12">
<a href="/search" class="text-sm font-semibold leading-6 text-gray-900">Browse</a>
<a href="/api-documentation" class="text-sm font-semibold leading-6 text-gray-900">API</a><a
href="/guidelines" class="text-sm font-semibold leading-6 text-gray-900">Guidelines</a><a
href="https://cheminf.uni-jena.de/" class="text-sm font-semibold leading-6 text-gray-900">About
Expand Down Expand Up @@ -53,6 +54,8 @@ class="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm
<div class="mt-6 flow-root">
<div class="-my-6 divide-y divide-gray-500/10">
<div class="space-y-2 py-6">
<a href="/search"
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Browse</a>
<a href="/api-documentation"
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">API</a>
<a href="/guidelines"
Expand Down
12 changes: 9 additions & 3 deletions resources/views/livewire/molecule-card.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@
<livewire:molecule-depict2d :smiles="$molecule->canonical_smiles">
</div>
<div class="flex flex-1 border-t flex-col space-y-2 p-4">
<div class="flex items-center">
@foreach (range(1, $molecule->annotation_level) as $i) <svg :key="{{ $i }}" class="inline text-yellow-400 h-5 w-5 flex-shrink-0" x-state:on="Active" x-state:off="Inactive" x-state-description='Active: "text-yellow-400", Inactive: "text-gray-200"' x-description="Heroicon name: mini/star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M10.868 2.884c-.321-.772-1.415-.772-1.736 0l-1.83 4.401-4.753.381c-.833.067-1.171 1.107-.536 1.651l3.62 3.102-1.106 4.637c-.194.813.691 1.456 1.405 1.02L10 15.591l4.069 2.485c.713.436 1.598-.207 1.404-1.02l-1.106-4.637 3.62-3.102c.635-.544.297-1.584-.536-1.65l-4.752-.382-1.831-4.401z" clip-rule="evenodd"></path></svg> @endforeach
</div>
<div class="flex flex-1 flex-col justify-end">
<p class="text-base font-medium text-gray-500">{{ $molecule->identifier }}</p>
</div>
<h3 class="text-sm font-bold text-gray-900">
<span aria-hidden="true" class="absolute inset-0"></span>
{{ $molecule->iupac_name }}
<h3 class="text-sm font-bold text-gray-900 capitalize">
@if($molecule->name)
{{ $molecule->name }}
@else
{{ $molecule->iupac_name }}
@endif
</h3>
</div>
</div>
Expand Down
92 changes: 61 additions & 31 deletions resources/views/livewire/molecule-details.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,33 +48,18 @@ class="flex items-baseline flex-wrap justify-between gap-y-2 gap-x-4 border-t bo
<div>
<dt class="font-medium text-gray-500"> Annotation Level</dt>
<div class="flex items-center">
<div class="flex items-center">
@if ($molecule->annotation_level > 0)
@foreach (range(0, $molecule->annotation_level) as $i)
<svg :key="index" v-for="index in molecule.annotation_level"
class="inline text-yellow-400 h-5 w-5 flex-shrink-0" x-state:on="Active"
x-state:off="Inactive"
x-state-description='Active: "text-yellow-400", Inactive: "text-gray-200"'
x-description="Heroicon name: mini/star" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd"
d="M10.868 2.884c-.321-.772-1.415-.772-1.736 0l-1.83 4.401-4.753.381c-.833.067-1.171 1.107-.536 1.651l3.62 3.102-1.106 4.637c-.194.813.691 1.456 1.405 1.02L10 15.591l4.069 2.485c.713.436 1.598-.207 1.404-1.02l-1.106-4.637 3.62-3.102c.635-.544.297-1.584-.536-1.65l-4.752-.382-1.831-4.401z"
clip-rule="evenodd"></path>
</svg>
@endforeach
@endif
@foreach (range(1, 5 - $molecule->annotation_level) as $j)
<svg :key="index" v-for="index in 5 - molecule.annotation_level"
class="inline text-gray-200 h-5 w-5 flex-shrink-0"
x-state-description='undefined: "text-yellow-400", undefined: "text-gray-200"'
x-description="Heroicon name: mini/star" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd"
d="M10.868 2.884c-.321-.772-1.415-.772-1.736 0l-1.83 4.401-4.753.381c-.833.067-1.171 1.107-.536 1.651l3.62 3.102-1.106 4.637c-.194.813.691 1.456 1.405 1.02L10 15.591l4.069 2.485c.713.436 1.598-.207 1.404-1.02l-1.106-4.637 3.62-3.102c.635-.544.297-1.584-.536-1.65l-4.752-.382-1.831-4.401z"
clip-rule="evenodd"></path>
</svg>
@endforeach
</div>
@foreach (range(1, $molecule->annotation_level) as $i)
<svg :key="index"
class="inline text-yellow-400 h-5 w-5 flex-shrink-0" x-state:on="Active"
x-state:off="Inactive"
x-state-description='Active: "text-yellow-400", Inactive: "text-gray-200"'
x-description="Heroicon name: mini/star" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd"
d="M10.868 2.884c-.321-.772-1.415-.772-1.736 0l-1.83 4.401-4.753.381c-.833.067-1.171 1.107-.536 1.651l3.62 3.102-1.106 4.637c-.194.813.691 1.456 1.405 1.02L10 15.591l4.069 2.485c.713.436 1.598-.207 1.404-1.02l-1.106-4.637 3.62-3.102c.635-.544.297-1.584-.536-1.65l-4.752-.382-1.831-4.401z"
clip-rule="evenodd"></path>
</svg>
@endforeach
</div>
</div>
</div>
Expand Down Expand Up @@ -125,6 +110,32 @@ class="mx-auto mt-8 grid max-w-3xl grid-cols-1 gap-6 sm:px-6 lg:max-w-7xl lg:gri
</div>
</div>
</section>
@endif
@if ($molecule->geo_locations && count($molecule->geo_locations) > 0)
<section>
<div class="bg-white border shadow sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h2 id="applicant-information-title" class="text-lg font-medium leading-6 text-gray-900">
Geolocations</h2>
</div>
<div class="border-t border-gray-200">
<div class="no-scrollbar px-4 py-4 lg:px-8 min-w-0">
<ul role="list" class="mt-2 leading-8">
@foreach ($molecule->geo_locations as $geo_location)
@if ($geo_location != '')
<li class="inline">
<a class="text-sm relative mr-2 inline-flex items-center rounded-md border border-gray-300 px-3 py-0.5"
target="_blank">
{{ $geo_location->name }}
</a>
</li>
@endif
@endforeach
</ul>
</div>
</div>
</div>
</section>
@endif
<section>
<div class="bg-white border shadow sm:rounded-lg">
Expand Down Expand Up @@ -152,7 +163,7 @@ class="text-sm font-medium text-gray-500 sm:flex sm:justify-between">
Name
</dt>
<div class="mt-1 break-all text-sm text-gray-900">
{{ $molecule->name }}
{{ $molecule->name ? $molecule->name : '-' }}
</div>
</div>
<div class="group/item -ml-4 rounded-xl p-4 hover:bg-slate-100">
Expand Down Expand Up @@ -284,13 +295,13 @@ class="ml-3 text-base text-gray-500">Formal Charge :
{{ $molecule->properties->total_atom_count }}</span></li>
<li class="py-5 flex md:py-0"><span
class="ml-3 text-base text-gray-500">Contains Sugar :
{{ $molecule->properties->contains_sugar }}</span></li>
{{ $molecule->properties->contains_sugar ? "True" : "False" }}</span></li>
<li class="py-5 flex md:py-0"><span
class="ml-3 text-base text-gray-500">Contains Ring Sugars :
{{ $molecule->properties->contains_ring_sugars }}</span></li>
{{ $molecule->properties->contains_ring_sugars ? "True" : "False" }}</span></li>
<li class="py-5 flex md:py-0"><span
class="ml-3 text-base text-gray-500">Contains Linear Sugars
: {{ $molecule->properties->contains_linear_sugars }}</span></li>
: {{ $molecule->properties->contains_linear_sugars ? "True" : "False" }}</span></li>
</ul>
</div>
</div>
Expand Down Expand Up @@ -543,6 +554,25 @@ class="ml-3 text-base text-gray-500"><b>Direct
</section>
@endif

@if ($molecule->related && count($molecule->related) > 0)
<section aria-labelledby="notes-title">
<div class="bg-white shadow border sm:overflow-hidden sm:rounded-lg">
<div class="divide-y divide-gray-200">
<div class="px-4 py-5 sm:px-6">
<h2 id="notes-title" class="text-lg font-medium text-gray-900">Tautomers</h2>
</div>
<div class="px-4 pb-5 sm:px-6">
<div class="mx-auto grid mt-6 gap-5 lg:max-w-none md:grid-cols-3 lg:grid-cols-2">
@foreach ($molecule->related as $tautomer)
<livewire:molecule-card :molecule="json_encode($tautomer)" />
@endforeach
</div>
</div>
</div>
</div>
</section>
@endif

@if ($molecule->is_parent)
<section aria-labelledby="notes-title">
<div class="bg-white shadow border sm:overflow-hidden sm:rounded-lg">
Expand Down

0 comments on commit 822760b

Please sign in to comment.