Orchard Harvest Crates
Batch ETL for orchard harvest crates: CSV import/export, packing math, and moisture on_error handling
One app.py with 1 table, 13 computed columns. Needs pixeltable>=0.7.16. Updated 2026-10-12.
app.py
"""Orchard Crates batch ETL built with Pixeltable.Import harvest crate rows from CSV, derive packing math with pixeltable.functions.math(abs/ceil/floor/round/sqrt/log/pow), validate moisture with an on_error=ignore UDF, thenexport an enriched CSV. Schema evolution drops the temporary ingest_batch column and addsshelf_life_days + density_pow. Drive with `python run.py` — no HTTP router.Layout: UDFs live in udfs.py; this file holds table models and @pxt.query functions.Run locally:pxt schema update app.py orchardpython run.py"""from __future__ import annotationsimport pixeltable as pxtimport pixeltable.functions as pxtffrom pixeltable.functions import math as pxtmfrom udfs import crate_tag, grade_lane, moisture_okTableModel = pxt.model_base()class Crates(TableModel, name='crates', has_default_idxs=False):"""One orchard harvest crate with packing math and moisture validation."""crate_id = pxt.Column(value=pxtf.uuid.uuid7(), primary_key=True)crate_code: pxt.Stringorchard: pxt.Stringvariety: pxt.Stringweight_kg: pxt.Floatlength_cm: pxt.Floatwidth_cm: pxt.Floatheight_cm: pxt.Floatmoisture_pct: pxt.Float# --- fn.math primary helpers ---volume_cm3 = length_cm * width_cm * height_cmabs_weight = pxtm.abs(weight_kg)weight_ceil = pxtm.ceil(weight_kg)weight_floor = pxtm.floor(weight_kg)weight_rounded = pxtm.round(weight_kg, 1)side_sqrt = pxtm.sqrt(pxtm.abs(length_cm))volume_log = pxtm.log(pxtm.abs(volume_cm3) + 1.0)density = weight_kg / (volume_cm3 / 1000.0) # kg / literdensity_pow = pxtm.pow(pxtm.abs(density) + 0.01, 0.5) # added in schema evolutionshelf_life_days = pxtm.floor(30.0 - pxtm.abs(moisture_pct - 12.0)) # evolution add# --- on_error UDF path ---moisture_checked = moisture_ok(moisture_pct)lane = grade_lane(variety, weight_kg)tag = crate_tag(crate_code, orchard)__indexes__ = [pxt.BtreeIndex(orchard),pxt.BtreeIndex(variety),pxt.BtreeIndex(lane),]@pxt.querydef by_orchard(orchard: str):"""Crates for one orchard (orchard index)."""return (Crates.where(Crates.orchard == orchard).select(Crates.crate_code,Crates.variety,Crates.weight_kg,Crates.density,Crates.lane,Crates.tag,Crates.shelf_life_days,).order_by(Crates.crate_code))@pxt.querydef heavy_lanes(min_weight: float):"""Crates at or above min_weight with packing math."""return (Crates.where(Crates.weight_kg >= min_weight).select(Crates.crate_code,Crates.orchard,Crates.weight_rounded,Crates.volume_cm3,Crates.density,Crates.density_pow,Crates.lane,).order_by(Crates.weight_kg, asc=False))@pxt.querydef moisture_failures():"""Rows where moisture_ok failed (on_error=ignore → errortype set)."""return (Crates.where(Crates.moisture_checked.errortype != None) # noqa: E711.select(Crates.crate_code,Crates.moisture_pct,Crates.moisture_checked,err=Crates.moisture_checked.errortype,msg=Crates.moisture_checked.errormsg,).order_by(Crates.crate_code))
What app.py declares
Each row links to its line.
- runs on insert
- stored
- index
- route
- crate_idcrate_codeorchardvarietyweight_kglength_cmwidth_cmheight_cmmoisture_pct
- volume_cm3 = length_cm * width_cm * height_cmL39
- abs_weight = pxtm.abs(weight_kg)L40
- weight_ceil = pxtm.ceil(weight_kg)L41
- weight_floor = pxtm.floor(weight_kg)L42
- weight_rounded = pxtm.round(weight_kg, 1)L43
- side_sqrt = pxtm.sqrt(pxtm.abs(length_cm))L44
- volume_log = pxtm.log(pxtm.abs(volume_cm3) + 1.0)L45
- density = weight_kg / (volume_cm3 / 1000.0)L46
- density_pow = pxtm.pow(pxtm.abs(density) + 0.01, 0.5)L47
- shelf_life_days = pxtm.floor(30.0 - pxtm.abs(moisture_pct - 12.0))L48
- moisture_checked = moisture_ok(moisture_pct)L51
- lane = grade_lane(variety, weight_kg)L52
- tag = crate_tag(crate_code, orchard)L53
- B-tree index on orchardL56
- B-tree index on varietyL57
- B-tree index on laneL58
No HTTP routes: a pipeline you insert into and query from Python.
Run it
Needs uv.
terminal
git clone https://github.com/pierrebrunelle/pixeltable-orchard-cratescd pixeltable-orchard-cratesuv syncuv run pxt schema update app.py orchard
Related apps
- Research Agent MemoryDurable, searchable long-term memory for an AI research assistant: per-user semantic recall, retrieval_udf lookups, tool calling and memory consolidation with custom aggregatesShares: B-tree indexes, UDFs
- Archery RangeMigrate archery-range scoring sessions from legacy JSON into Pixeltable, score with date-aware computed columns, and run as an incremental scheduled pipelineShares: B-tree indexes, UDFs
- Apiary AdvisorRAG + tool-calling beekeeping advisor: custom embedding index, table-as-UDF agent pipeline, expr_udf mite mathShares: B-tree indexes, UDFs