Skip to content
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
c28f809
Inlines aggregated feedback into study results
falquaddoomi Jun 19, 2026
cbcf5d1
Sends back min/max (hardcoded to 0, 100) for confidence facet so the …
falquaddoomi Jun 19, 2026
5b73e25
Fixes edge case where a series has no corresponding OntologyTermRatin…
falquaddoomi Jun 19, 2026
f91b222
Adds handling for the 'query' param submitted by the samples search b…
falquaddoomi Jun 19, 2026
4fc0421
Added missing 're' import required by cbcf5d19b21cf7b99bc535ad9fec0f1…
falquaddoomi Jun 19, 2026
1110d09
Updates frontend types to allow sample.description to be nullable
falquaddoomi Jun 19, 2026
3b92295
Adds ExternalDbRefs model, migration, loader for series->external db …
falquaddoomi Jun 19, 2026
0871560
Adds external_dbs to GEOSeries serializer
falquaddoomi Jun 19, 2026
8790a87
Disables study search results caching b/c feedback invalidates the cache
falquaddoomi Jun 19, 2026
722c224
Reduces feedback to just the number of votes, not the actual rating
falquaddoomi Jun 19, 2026
f2a3c07
frontend: merge in other prs, fixes, new feats
vincerubinetti Jun 22, 2026
1e5d456
style tweaks
vincerubinetti Jun 22, 2026
74b529b
Adds facet models, migrations, mgmt command for computing them. Chang…
falquaddoomi Jun 23, 2026
73151d2
Updates views, serializers for new database format + filters, global …
falquaddoomi Jun 23, 2026
25c61bc
Updates frontend types, mappings for new database field format
falquaddoomi Jun 23, 2026
ce46a00
Adds mgmt command to normalize db names
falquaddoomi Jun 23, 2026
42f0e6e
Adds facet entries to db normalization mgmt command
falquaddoomi Jun 23, 2026
57d22aa
tweak wording, fix prev commit, remember stats show
vincerubinetti Jun 23, 2026
4d4891a
make stats panel look less annoying
vincerubinetti Jun 23, 2026
19d828b
change feedback popup wording
vincerubinetti Jun 23, 2026
fea174d
fix db type
vincerubinetti Jun 23, 2026
74f6fdd
add frontend test workflow
vincerubinetti Jun 23, 2026
17b1064
modernize eslint and prettier configs
vincerubinetti Jun 23, 2026
27fbebf
show study feedback in ui
vincerubinetti Jun 23, 2026
db9b6ec
fix type check, reinstall packages
vincerubinetti Jun 23, 2026
04a19be
Avoids fronted @rollup/rollup-linux-arm64-gnu crash/collision with Da…
falquaddoomi Jun 23, 2026
88ca285
Allows users to replace their vote on a study, prevents multiple vote…
falquaddoomi Jun 23, 2026
1fea681
Indexes organism column in samples for faster species resolution for …
falquaddoomi Jun 23, 2026
e530812
Adds /api/stats endpoint
falquaddoomi Jun 23, 2026
843c6a4
Updates frontend Home to reference stats field `terms` for "tissues &…
falquaddoomi Jun 23, 2026
605e13e
fix 404 redirect
vincerubinetti Jun 23, 2026
3431e44
fix sample search box disappear
vincerubinetti Jun 23, 2026
4402152
fix stat types, tweak appearance
vincerubinetti Jun 23, 2026
fd13069
incorp ui feedback
vincerubinetti Jun 23, 2026
6ef7bbf
fix types
vincerubinetti Jun 23, 2026
4b3b0c0
fix database pills
vincerubinetti Jun 23, 2026
3840110
hide pagination when 0 count
vincerubinetti Jun 23, 2026
4c8ad6d
use database link from backend
vincerubinetti Jun 23, 2026
96e1458
Returns GEOSeries.platform as a list[str] instead of just str, update…
falquaddoomi Jun 23, 2026
c866cef
Trims leading and trailing whitespace from database URLs, external IDs
falquaddoomi Jun 23, 2026
cc74649
re-add db links, touch up side panel, misc tweaks
vincerubinetti Jun 24, 2026
609adf5
remove svgr (not used)
vincerubinetti Jun 24, 2026
0cd9402
split stats tissue and disease?
vincerubinetti Jun 24, 2026
ed662d2
tweak home page tile styles
vincerubinetti Jun 24, 2026
d81442c
Modifies name, type query for meta to run just one query
falquaddoomi Jun 24, 2026
3bc060d
Removes caching of stats since feedback will change this; reconsider …
falquaddoomi Jun 24, 2026
731bb98
Adds back in caching of most db-wide stats except Feedback, which is …
falquaddoomi Jun 24, 2026
8e93a1a
fix db link replacement
vincerubinetti Jun 24, 2026
9912a45
touch up sample dialog
vincerubinetti Jun 24, 2026
6ae6b94
format
vincerubinetti Jun 24, 2026
5087031
Increase memcached max item size, total memory
falquaddoomi Jun 27, 2026
939e52b
Adds option to immediately flush timed output
falquaddoomi Jun 27, 2026
9eed622
Adds series_set, optimizes search_onto to not use limit if null is su…
falquaddoomi Jun 28, 2026
9e41cfb
Makes manager methods more efficient
falquaddoomi Jun 28, 2026
19bc985
Updates SEARCH_MAX_RESULTS to pass null to improve query planning, ad…
falquaddoomi Jun 28, 2026
600587b
Makes series samples action query series_set rather than series_id
falquaddoomi Jun 28, 2026
829b4e0
Fixes array query for GEOSeries.samples action
falquaddoomi Jun 28, 2026
7d87ce6
fix cart delete bug, partially fix refine.bio, misc fixes
vincerubinetti Jun 29, 2026
f3a3b32
dont allow 0-sample refine.bio export
vincerubinetti Jun 29, 2026
847de27
fix clear cart button
vincerubinetti Jun 29, 2026
c300faa
Adds requested BSD-3 license to repo
falquaddoomi Jun 29, 2026
4c7d9c0
Squashes migrations from 0043 to 0046 to skip expensive index that's …
falquaddoomi Jun 29, 2026
e300047
use tsconfigpaths
vincerubinetti Jun 30, 2026
b2c1c6b
Excludes migration that needs to not be in a transaction from squashe…
falquaddoomi Jun 30, 2026
20b0ebc
common sample details empty placeholder
vincerubinetti Jul 1, 2026
0cfccf5
touch up home page stats
vincerubinetti Jul 1, 2026
b93c392
Materializes GEOSeries.samples_ct, adds indices, optimizes search. Ch…
falquaddoomi Jul 1, 2026
51741db
Minor comment clarifications in host_load_db.sh
falquaddoomi Jul 1, 2026
6877239
Acquires new db dump if needed before running host_load_db.sh
falquaddoomi Jul 1, 2026
9d01a64
Adds proxied env config that tunes the db to run on an e2-medium
falquaddoomi Jul 2, 2026
ea077f1
Allows specifically meta2onto.org to use the backend
falquaddoomi Jul 2, 2026
75046ed
Removes e2-med postgresql config for now, until we debug it
falquaddoomi Jul 2, 2026
e8d2a80
Makes frontend use meta2onto.org
falquaddoomi Jul 2, 2026
d61f8d2
API index now shows views in addition to viewsets
falquaddoomi Jul 2, 2026
43aea18
Gunicorn workers now settable via WEB_WORKERS (default 4), timeout vi…
falquaddoomi Jul 2, 2026
202dcaa
Pulls tissue, disease counts from SearchTerm; counts MONDO for diseas…
falquaddoomi Jul 2, 2026
83e92be
Adds positive study annotations model, mgmt command update, migration.
falquaddoomi Jul 4, 2026
a3b40b4
Adds materialized views for series->tech, series->organism. Adds orga…
falquaddoomi Jul 4, 2026
389e484
Adds classificiations as a proper model field
falquaddoomi Jul 4, 2026
d5a01f6
Adds organism field, filtering. Makes tech filtering use materialized…
falquaddoomi Jul 4, 2026
b7dcad7
Adds env var for easier db logging
falquaddoomi Jul 4, 2026
c480b75
add organism pills, tweak colors
vincerubinetti Jul 6, 2026
df32d36
Changes classification from 'negative' to 'unlabeled' for non-positiv…
falquaddoomi Jul 6, 2026
486f4b0
Changes refine.bio column from geo to gse per new dataset format
falquaddoomi Jul 6, 2026
7199720
Allows filtering on Classification; updates frontend to filter to 'Un…
falquaddoomi Jul 6, 2026
ebd5cfc
Removes .only() clause from search endpoint since the serializer requ…
falquaddoomi Jul 6, 2026
6a70900
Parameterizes import_external_db_refs gse column since it's gse in th…
falquaddoomi Jul 6, 2026
28ad954
remove needless backticks
vincerubinetti Jul 6, 2026
8d49c25
add link to gse
vincerubinetti Jul 7, 2026
7d5faae
GEOSeriesDatabase importer now pulls from geo_series.parquet's biopro…
falquaddoomi Jul 7, 2026
e76fe82
Fixes technology filter to select all records that have at least the …
falquaddoomi Jul 7, 2026
a6fc089
Fixes tissue/disease counts via distinct on term; thanks, PH, for cat…
falquaddoomi Jul 7, 2026
eaa8719
Increased worker timeout in proxied env to 120s
falquaddoomi Jul 7, 2026
0bc22c9
For stats, intersects Series, Sample queries against SearchTerm to li…
falquaddoomi Jul 7, 2026
fc4655c
Added SearchSeriesPlatform view to improve platform joins
falquaddoomi Jul 7, 2026
f6709a1
Cleaned up various imports, migrated model property to serializer, fi…
falquaddoomi Jul 7, 2026
5b1918d
Adds cmd to warm stats cache, adds to api launch premable
falquaddoomi Jul 7, 2026
09d6a2d
selection whitespace
vincerubinetti Jul 7, 2026
17eafc8
Factors methods out of /api/stats so the precompute cmd can use them,…
falquaddoomi Jul 8, 2026
8e535c8
Revert to default cache timeout
falquaddoomi Jul 8, 2026
2153fe9
fix: fixes refine.bio export POST request
phicks22 Jul 9, 2026
52ec146
fix refineBioStudyIds
vincerubinetti Jul 9, 2026
168b8c1
Removes site-statistic compilation from launch API preamble, moves it…
falquaddoomi Jul 9, 2026
b4995a0
Corrects sample count resolution in populate_site_statistics mgmt com…
falquaddoomi Jul 9, 2026
202a32c
Fixes invalid field ref w/cart sharing
falquaddoomi Jul 9, 2026
a641136
Updates another GEOSeries.series_id ref to GEOSeries.gse in an older …
falquaddoomi Jul 9, 2026
c1e1ddd
Allowed refine.bio succes to be null, still reports error if it's false
falquaddoomi Jul 9, 2026
a9dff7c
refine.bio === false
vincerubinetti Jul 9, 2026
5cf9bf4
change conditional again
vincerubinetti Jul 9, 2026
885b613
link to refine.bio api docs
vincerubinetti Jul 9, 2026
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
85 changes: 85 additions & 0 deletions .github/workflows/test-frontend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Test frontend

on:
pull_request:

defaults:
run:
working-directory: frontend

jobs:
test-build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Bun
uses: oven-sh/setup-bun@v2

- name: Install packages
run: bun install

- name: SSH debug
if: runner.debug == '1'
uses: mxschmitt/action-tmate@v3

- name: Run test
run: bun run build

test-types:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Bun
uses: oven-sh/setup-bun@v2

- name: Install packages
run: bun install

- name: SSH debug
if: runner.debug == '1'
uses: mxschmitt/action-tmate@v3

- name: Run test
run: bun run test:types

test-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Bun
uses: oven-sh/setup-bun@v2

- name: Install packages
run: bun install

- name: SSH debug
if: runner.debug == '1'
uses: mxschmitt/action-tmate@v3

- name: Run test
run: bun run test:lint

test-format:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Bun
uses: oven-sh/setup-bun@v2

- name: Install packages
run: bun install

- name: SSH debug
if: runner.debug == '1'
uses: mxschmitt/action-tmate@v3

- name: Run test
run: bun run test:format
179 changes: 179 additions & 0 deletions backend/src/api/management/commands/compute_global_facets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
"""
Populates the Facet model using the currenty-loaded GEOSeries, GEOPlatforms,
and GEOSamples models. These facets are returned by the study search endpoint
instead of being dynamically computed at query time.

See the Facet model for more details on the structure of the facet data and
the rationale for precomputing it.
"""

from django.core.management.base import BaseCommand

from django.db import models, connection, transaction

from api.models import Facet, FacetEntry, GEOSeries, GEOPlatform, GEOSeriesToGEOPlatforms, GEOSample
from api.utils.timing import timed

def populate_study_size():
# find the minimum and maximum number of samples
# associated with any series in the database
min_size = (
GEOSeries.objects.annotate(sample_count=models.Count("samples"))
.aggregate(min_size=models.Min("sample_count"))
.get("min_size", 0)
)
max_size = (
GEOSeries.objects.annotate(sample_count=models.Count("samples"))
.aggregate(max_size=models.Max("sample_count"))
.get("max_size", 0)
)

Facet.objects.create(
name="Study Size",
min=min_size,
max=max_size
)

def populate_confidence():
# hardcoded to 0-100, but we might change it to the min/max confidence
# over the dataset at some point
Facet.objects.create(
name="Confidence",
min=0,
max=100
)

def populate_platforms():
# populates the Plaforms facet with each unique platform
# and the number of studies overall associated with that platform
facet = Facet.objects.create(
name="Platforms"
)

qs = GEOPlatform.objects.raw("""
SELECT
PL.gpl,
SUM(array_length(GEPL.platforms, 1)) AS total
FROM api_geoplatform AS PL
INNER JOIN api_geoseriestogeoplatforms GEPL
ON PL.gpl = ANY(GEPL.platforms)
GROUP BY PL.gpl
""")

for platform in qs:
FacetEntry.objects.create(
facet=facet,
name=platform.gpl,
count=platform.total
)

def populate_technologies():
"""
Populates the Technologies facet with each unique technology and the number
of studies overall associated with that technology.

Note that we can't query via GEOPlatform as we do in populate_platforms(),
since we're not returning GEOPlatform primary keys. Instead we opt for a
regular raw query.
"""
with transaction.atomic():
facet = Facet.objects.create(name="Technologies")

with connection.cursor() as cursor:
cursor.execute("""
SELECT
PL.technology,
SUM(array_length(GEPL.platforms, 1)) AS total
FROM api_geoplatform AS PL
INNER JOIN api_geoseriestogeoplatforms GEPL
ON PL.gpl = ANY(GEPL.platforms)
GROUP BY PL.technology
""")

rows = cursor.fetchall()

FacetEntry.objects.bulk_create([
FacetEntry(
facet=facet,
name=technology,
count=total,
)
for technology, total in rows
])

def populate_databases():
"""
Populates the Databases facet with each unique database and the number of
studies overall associated with that database.

Note that we can't query via GEOPlatform as we do in populate_platforms(),
since we're not returning GEOPlatform primary keys. Instead we opt for a
regular raw query.
"""
with transaction.atomic():
facet = Facet.objects.create(name="Databases")

with connection.cursor() as cursor:
cursor.execute("""
SELECT
database,
COUNT(DISTINCT series_id) AS total
FROM (
SELECT
database,
series_id
FROM api_externaldbrefs
WHERE database IS NOT NULL AND database <> ''

UNION

SELECT
database,
series_id
FROM api_geoseriesdatabase
WHERE database IS NOT NULL AND database <> ''
) AS combined
GROUP BY database
""")

rows = cursor.fetchall()

FacetEntry.objects.bulk_create([
FacetEntry(
facet=facet,
name=database,
count=total,
)
for database, total in rows
])

# definitions of which facets we want to compute
# - the key in this dict is the name of the facet, the type
# (minmax or categorical) determines which attributes of the Facet
# model are populated.
# - 'method' is a function that computes the facet values and yields dicts for
# each facet value
FACETS = [
("Study Size", "minmax", populate_study_size),
("Confidence", "minmax", populate_confidence),
("Platforms", "categorical", populate_platforms),
("Technologies", "categorical", populate_technologies),
("Databases", "categorical", populate_databases),
]

class Command(BaseCommand):
help = "Compute Facet model contents based on GEOSeries, Samples, and Platforms models."

def add_arguments(self, parser):
pass

def handle(self, *args, **opts):
# drop all the entries in the Facet table before recomputing
# (this implicitly drops all the associated FacetEntry rows via a
# cascade delete)
Facet.objects.all().delete()

for facet_name, facet_type, method in FACETS:
with timed(label="- Elapsed", print_method=self.stdout.write):
self.stdout.write(f"Computing facet: {facet_name} ({facet_type})")
method()
Loading