Bulk import and export

CSV, Benchling and plate-reader files in; CSV out for downstream analysis.

Most labs already have data: in CSVs from instruments, in Benchling, in legacy spreadsheets, in plate-reader outputs. This page covers how to land that data in Dalea in bulk, and how to get data back out for downstream analysis in Python or R.

What you can import

FormatSourceLands in
CSV (.csv)Plate readers, qPCR cyclers, flow cytometers, manual exportsEntity tables, result tables or inventory, through the mapping wizard
Excel (.xlsx)Lab spreadsheetsThe same wizard; one mapping can span several sheets and several target tables
JSON DataPackage (.json)A Dalea environment export, or a pipeline that emits the DataPackage envelopeObject rows in an existing environment
BenchlingA live Benchling tenant, over its APIA new environment, plus projects, documents, files and inventory

For spreadsheets those two extensions are the whole list. A .tsv or a legacy binary .xls is refused by the parser before mapping begins, so re-save it as .csv or .xlsx first.

JSON import is not free-form. The file has to be either Dalea's own DataPackage envelope (type: "data" plus metadata and tables) or a Benchling extractor export; anything else is rejected with "Invalid data package format". Raw instrument JSON has to become a CSV or XLSX before the mapping wizard will take it; the wizard's "Work on it with the AI assistant" destination attaches the file to a chat, where the assistant can reshape it into one.

The mapped spreadsheet import into the data model is all-or-nothing. The engine parses, maps, resolves references, validates and inserts inside one transaction, and anything short of a fully green run is rolled back, so a retry can never double-insert the rows that already passed. The other two paths are not all-or-nothing: a JSON DataPackage import commits the rows that validate and answers HTTP 207 with a per-row error list, and a result-CSV import records the rows that validate and reports the count that failed.

CSV import: registering objects in bulk

  1. Drop the file into Dalea

    Drag a CSV or XLSX anywhere in the app. The Import into Dalea wizard opens at the drop point and previews the first 8 rows and 10 columns locally, before anything is uploaded. "Import a file…" in the create menu (⌘.) opens the same wizard.

  2. Choose “Import into data model”

    The wizard offers a destination per file kind; for a spreadsheet those are the data model, a new document, results, inventory, the AI assistant and plain upload. The first row is always read as the header row, and there is no headerless mode, so add a header row to a bare instrument dump before importing.

  3. Pick the environment

    Then, optionally, a project. Rows landing in project-scoped tables are filed under it, and the import refuses to run without one when any target table is project-scoped.

  4. Map columns

    Draft mapping with AI reads the file and the environment schema and proposes the wiring; Map manually in workbook opens the mapping drawer instead. Each source header points at one table and one column. Leave a header unmapped to skip it. Columns cannot be created during an import: add them in the environment designer and commit the schema change first. (An AI draft may propose whole new tables, and those go to the workbook's staging view for review, not into the import.)

  5. Resolve references

    A source column mapped onto a reference column also needs a key column on the referenced table: the column whose value the source text is matched against. Source values that are already row UUIDs, as in a Dalea CSV export, resolve on their own and need no key.

  6. Dry run, then Import Data

    Dry run executes the whole pipeline in a transaction and rolls it back. Import Data stays disabled until the dry run comes back green, and asks for a second, deliberate click before it writes.

Recording results from a file

Two ways in:

  • The wizard's Import as results destination. Pick the environment and the result table, then map each source column onto a dimension or a measurement.
  • Import CSV on a result table in the workbook, which opens the same dialog directly. It shows a five-row preview of the source, warns about dimensions no column feeds, and reports how many records were created and how many failed.

Every result import creates its own new batch, labelled with the file name and carrying origin type import. You cannot append to an existing batch, and a batch has no open or closed state: to correct one, record a successor that supersedes it.

Plate readers get no special treatment in the file import: there is no well-to-sample join. Use the 96-Well Plate block instead. Its grid view has one row per well, so you lay the samples out on the plate, paste the reader's column of values into a measurement column, and click Record Results. That writes one result record per filled well into a new batch with origin type well_plate, against the result table the block is bound to. Recording again supersedes the batch it created ("Re-record Results").

Dalea stores the readings. It does not fit standard curves: fit in a Python block or the AI assistant's sandbox and bring the derived concentrations back as their own result import.

Units on import

A number column is recorded in the unit set on the column, so an imported file must be in that unit, or say which unit it is in. When a header carries a unit such as Weight (lb) for a column in grams, the mapping pre-fills a source unit and every value is converted on the way in; a mapping can also set sourceUnit by hand. Cells that carry their own compatible unit (14.5 kg) convert too; a unit of another kind, or an unknown one, is reported by name instead of being silently truncated. Exports keep the bare column name as the header, and inventory exports add a _unit column holding each item's unit code.

Benchling import

Benchling import is a live API pull, not a file upload. Supply the tenant URL (https://<tenant>.benchling.com), the client id and the client secret of a Benchling app, name the environment to create, and tick what to bring across under "What to Import":

  • Data model (schemas & types)
  • Data records, the rows themselves
  • Projects & folders
  • Notebook entries (as documents)
  • File attachments
  • Inventory (locations, boxes, plates & containers), Benchling's storage tree

One job creates one environment, with one table per Benchling schema: entity schemas become entity tables, assay-result schemas become result tables. Registered entities keep their Benchling registry ID as their Dalea display ID. The job runs in the background with live progress, and finishes with a summary of tables, columns, objects, references resolved, references left dangling and warnings.

There is also a file path for an export you already extracted: the environment page's Import Data button takes a .json file in either the Benchling extractor shape or the DataPackage shape. Preview runs the engine and rolls it back; Import Data commits. Zip archives are not accepted.

When a dry run is not green

The dry run runs the full pipeline and rolls it back, so nothing is written. Typical failures:

  • A required column is empty in some rows.
  • A value does not fit the column type, or falls outside a number column's min/max.
  • An enum value is not in the column's allow-list.
  • A reference key matches no row in the referenced table.
  • A mapped source header is missing from the chosen sheet, or a reference column has no mapping feeding it.

What comes back is a report, not an editor. Per table: a status, ok and failed counts, a histogram that collapses same-shape errors into one entry, and a sample of up to ten failing rows, each with the row index, the column, the value and a suggested fix. Dangling references are aggregated by table and column with sample keys and a row count.

You fix the source file or the mapping and run the dry run again. Nothing commits until it is green.

Export

Entity tables and result tables each have an Export CSV button in the workbook. The file is written into the workspace's "Data Exports" folder rather than downloaded, so it is ready to attach to a chat or open in a sandbox. The export_data MCP tool drives the same endpoint, so the assistant can export a table for you.

Inventory has its own Export CSV, on the "Import / Export (Experimental)" tab of inventory settings: it builds the file in the browser and downloads it, covering every container and placement.

Inside a document, the blocks that hold a table (Spreadsheet, Lookup Table, Registration Table, Well Plate and Python) carry a download icon in their header that saves what the block is currently showing as a CSV, straight to your machine. Saved-query pages and Chart blocks have no export button; export the table or the block underneath them instead.

What a table CSV contains:

PartShape
Entity meta columns_id, _display_id, then one column per table column
Result meta columns_record_id, _batch_id, _recorded_at, then the dimension and measurement columns
Reference cellsThe referenced row's UUID, plus a <column> (display id) companion column beside it. The UUID form re-imports with no reference mapping needed
Rows includedLive data only: archived rows and superseded result records are left out

Exports are whole-table. Filters typed into the grid are view state and are not applied, and CSV is the only format the endpoint accepts. Output stops at 100,000 rows or 50 MB, whichever comes first, and the response reports truncated when it hits the cap. To export a slice, make the slice its own table or result batch.

For a whole environment there is a second shape: GET /environments/{id}/data/export returns a JSON DataPackage of the object rows, archive metadata included, narrowable with ?tables=id1,id2. That is the same envelope the JSON import accepts, so it round-trips.

Bioinformatician pattern: round-trip analysis

A common pattern:

  1. Run the experiment in Dalea, capture results in a result batch.
  2. Export the table as CSV.
  3. Run downstream analysis in Python (PK modelling, NCA, dose-response fits) or R (DESeq2, mixed-effects models).
  4. Re-import the analysis output as a new result batch in a separate result table (e.g. PK parameters with auc_0_24, cmax, tmax, cl_per_kg).
  5. A study-summary document can now embed both raw concentrations and derived parameters side by side.

The provenance graph records both ends: the export as a data_export run, and the re-import as a data_import run that ties the source file to the rows and batches it created.

Tips

Every import is recorded

The audit event carries the operator, the timestamp, the mapping id, the project, the dry-run flag, the status and the ok/failed row counts. The source file itself lives in the provenance graph, on the data_import run linking it to the rows and batches it produced. No audit reason is asked for at import time: reason-for-change is captured on schema commits and record edits.

A dry run is the real thing, rolled back

The mapping-based import goes through Dry run first, whatever its size: Import Data is disabled until the run comes back green. It is the same engine, the same transaction and the same report as the real apply, just rolled back at the end, so a green preview faithfully predicts the commit. The JSON path offers the same preview under Preview but does not force it, and a result-CSV import has no preview step.

What's next