Recording results

Cytokine ELISA: standard curve, replicates, dimensions.

Once you have a schema, recording results is a small ritual: assemble the measurements, then commit them as one result batch. A batch is created complete and is never edited in place, so a correction means recording a superseding batch. This page walks through that ritual using a realistic cytokine ELISA on plasma samples from the PK study.

The example

We are quantifying mouse IFN-γ in plasma collected from study DLA-7. A standard 8-point curve plus blanks and QC pools, samples in duplicate, OD₄₅₀ readout, fitted 4-parameter logistic.

The plate layout looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
A
S1
S1
·
B
S2
S2
·
C
S3
S3
·
D
S4
S4
·
E
S5
S5
·
F
S6
S6
·
G
S7
S7
·
H
S8
S8
·
Standard curve (8 pts × 2)BlankQC (low/mid/high)Sample (32 wells, 2 mice × 4 tp × 2)
Hover any well for details. Dalea's 96-well-plate block stores this layout and joins it to your sample table by mouse + timepoint.
96-well layout for the assay. Hover any well to see what's in it.

The standard curve

Dalea stores the raw OD readings; it does not fit curves. The 4-parameter-logistic fit is something you run yourself, in a Python block in the same document, which reads the plate with get_block(), or in the sandbox from chat. You then record the back-calculated concentrations as their own measurement. Click a sample below to project its OD onto the curve:

1101001000IFN-γ concentration (pg/mL, log scale)0.01.02.03.0OD₄₅₀
4-parameter logistic fit (Dalea computes A, B, C, D automatically). Click a sample to project its OD onto the curve.
4-PL fit. The samples shown are real shapes from a mouse with low IFN-γ at baseline rising to ~1100 pg/mL at 4 h.

Recording in Dalea

  1. Know what a batch is

    A batch is one recording event. It carries an operator (recordedBy), a timestamp (recordedAt), an origin, and a status of active or superseded. There is no draft state: the batch and its records are written in a single call.

  2. Specify the schema and its columns

    Pick the result table (e.g. plasma cytokines) and confirm which columns are dimensions, the coordinates that place each record, and which are measurements. For this assay the dimensions are animal, timepoint_h, analyte and replicate; the measurement is the OD reading.

  3. Enter or import measurements
    Data → Cytokines → Import CSV, or a block in a document

    Four routes, one per batch origin:

    • Well plate block. Lay the plate out in a document, fill the sheet view (pasting the plate-reader export straight into it works), and press Record Results. Origin well_plate.
    • Registration table block. A grid bound to the result schema, one row per record, same Record Results button. Origin data_entry.
    • Import CSV. On the result table in Data, map the CSV columns to dimensions and measurements. Origin import.
    • API or SDK. POST the records to /results/batches. Origin api.
  4. Correct by re-recording

    Nothing seals a batch, because nothing ever reopens one. To fix a value you record a replacement batch that names the old one (supersedesBatchId, with an optional supersedeReason); the old batch is marked superseded and the reason is stored on it. Pressing Re-record Results in a well plate or registration table block does exactly this. Data integrity without making typos painful: you correct by re-recording, never by overwriting.

Migrating an existing assay history out of Benchling is a different path: you connect Dalea to your Benchling tenant with a tenant URL, client id and client secret, and run an import job that pulls schemas, entries, data, files and storage in one run. See bulk import and export.

Querying results

Once recorded, results are queryable from a lookup-table block, from a chart pointed at one, and from the AI assistant:

Three questions the builder answers
  • Concentration per dose group: root the query at animals, hop into the result schema in Aggregated mode, group by study_group and take mean of concentration_ug_ml.
  • The full time course: the same hop in Raw rows mode returns one row per record, timepoint_h included. Point a line chart at it and let the chart average per timepoint.
  • How many measurements you actually have: the count aggregation, or the hop's "Include group size (n)" option.

None of these need SQL. You configure them in the query builder, save them, and embed the saved query in a document through a lookup-table block. Anything the seven aggregations (mean, median, sum, min, max, count, latest) cannot express, a duplicate CV or a trapezoidal AUC for instance, belongs in a Python block over the queried rows.

Replicate handling

Replicates are an extra dimension column. Recording duplicate samples means two records sharing all dimensions except replicate = A | B. The chart and aggregation engine collapses replicates into one value per group. On bar, strip (dot plot) and box-plot charts a Show individual points checkbox, on by default, draws every replicate on top of the aggregate. Line, area, scatter, histogram and pie charts do not offer it.

Auditability

Every result batch records:

  • the operator, as recordedBy
  • recordedAt, the moment the batch was committed
  • the origin: well_plate, data_entry, import or api, plus the id and name of the block it came from when a document block recorded it
  • the project and document it was recorded under, when there is one

When a batch is superseded, the retired batch also keeps supersededAt, supersededByUser and the supersedeReason you gave, so "who replaced this, and why" is answerable from the batch itself. Content hashes of an uploaded source file live in the provenance layer, against the file, not on the batch.

Signing works at the document level, not the batch level. A batch becomes write-locked (finalizedAt) when its source document is approved under a finalize_data review policy, and that approval is what carries the electronic signature. The one batch operation that requires a signature of its own is permanently deleting a batch that has already been archived.

What's next