Lab Accession
Lab sample accession queue API: three related tables, parallel writers and racing claims
One app.py with 3 tables, 3 computed columns, 7 HTTP routes. Needs pixeltable[serve]>=0.7.14. Updated 2026-09-28.
app.py
"""Lab Accession API built with Pixeltable.pxt schema update app.py labpxt service run app.py lab"""import pixeltable as pxtimport pixeltable.functions as pxtffrom pixeltable.serving import FastAPIRouterfrom udfs import priority_name, station_label, urgency_band# ---- tables ----TableModel = pxt.model_base()class Stations(TableModel, name='stations'):station_id = pxt.Column(type=pxt.String, primary_key=True)name: pxt.Stringcapacity: pxt.Intlabel = station_label(name, capacity)class Samples(TableModel, name='samples'):accession_id = pxt.Column(type=pxt.String, primary_key=True)specimen: pxt.Stringpriority: pxt.Intreceived_at: pxt.Stringbatch_code: pxt.String | Nonepriority_label = priority_name(priority)class Assignments(TableModel, name='assignments', has_default_idxs=False):id = pxt.Column(value=pxtf.uuid.uuid7(), primary_key=True)accession_id: pxt.Stringstation_id: pxt.Stringpriority: pxt.Intdelayed_min: pxt.Intstatus: pxt.Stringclaimed_by: pxt.String | Noneurgency = urgency_band(priority, delayed_min)__indexes__ = [pxt.BtreeIndex(station_id), pxt.BtreeIndex(status)]# ---- queries ----@pxt.querydef station_queue(station_id: str):"""Work for one station, most urgent first."""return Assignments.where(Assignments.station_id == station_id).select(Assignments.id, Assignments.accession_id, Assignments.urgency, Assignments.status, Assignments.claimed_by).order_by(Assignments.priority, asc=False)@pxt.querydef batch(batch_code: str):"""Samples received in one batch."""return Samples.where(Samples.batch_code == batch_code).select(Samples.accession_id, Samples.specimen, Samples.priority_label).order_by(Samples.accession_id)# ---- routes ----lab_api = FastAPIRouter(name='lab_api')lab_api.add_insert_route(Stations, path='/stations', inputs=[Stations.station_id, Stations.name, Stations.capacity],outputs=[Stations.station_id, Stations.label])lab_api.add_insert_route(Samples, path='/samples',inputs=[Samples.accession_id, Samples.specimen, Samples.priority, Samples.received_at,Samples.batch_code],outputs=[Samples.accession_id, Samples.priority_label])lab_api.add_insert_route(Assignments, path='/assignments',inputs=[Assignments.accession_id, Assignments.station_id, Assignments.priority,Assignments.delayed_min, Assignments.status, Assignments.claimed_by],outputs=[Assignments.id, Assignments.urgency])lab_api.add_update_route(Assignments, path='/assignments/claim', inputs=[Assignments.status, Assignments.claimed_by],outputs=[Assignments.id, Assignments.status, Assignments.claimed_by])lab_api.add_compute_route(Assignments, path='/urgency', inputs=[Assignments.priority, Assignments.delayed_min],outputs=[Assignments.urgency])lab_api.add_query_route(path='/stations/queue', query=station_queue, method='get')lab_api.add_query_route(path='/batches', query=batch, method='get')
What app.py declares
Each row links to its line.
- runs on insert
- stored
- index
- route
serves lab_api
- POST/stationsinsert, stationstakes station_id, name, capacity; returns station_id, labelL67
- POST/samplesinsert, samplestakes accession_id, specimen, priority, received_at, batch_code; returns accession_id, priority_labelL69
- POST/assignmentsinsert, assignmentstakes accession_id, station_id, priority, delayed_min, status, claimed_by; returns id, urgencyL73
- POST/assignments/claimupdate, assignmentstakes status, claimed_by; returns id, status, claimed_byL77
- POST/urgencycompute, assignmentstakes priority, delayed_min; returns urgencyL79
- GET/stations/queuequery, station_queuetakes station_idL81
- GET/batchesquery, batchtakes batch_codeL82
Run it
Needs uv. The routes then answer on port 8000.
terminal
git clone https://github.com/pierrebrunelle/pixeltable-lab-accessioncd pixeltable-lab-accessionuv syncuv run pxt schema update app.py labuv run python seed.py labuv run pxt service run app.py lab --port 8000
Related apps
- Forge Heat CyclesForge heat-cycle registry API: B-tree indexes, chained risk UDFs, and parallel shop-floor writersShares: B-tree indexes, UDFs
- Climbing Route ToposClimbing-route topo registry API: photo uploads with thumbnails, grayscale copies, grade bands and index-backed crag lookupsShares: B-tree indexes, UDFs
- Warehouse Pick ListsWarehouse pick-list REST API: units, pick zones, waves and tote labels as incremental computed columns over Json order linesShares: B-tree indexes, UDFs