Skip to content

Separation and Fractionation

Culsma separates material with sep(...), selects source-local separation portions inside transfer statements, and creates ordered fractions with frac(...).

Both forms take a sample and a program.

sep(...)

sep(...) splits one container into a fixed two-slot group.

text
let g = sep(sample = lysate, program = centrifuge_program(drive = 12000g));

The result is a sep_container_group. Access its slots with group[0] and group[1].

text
output << [g[0]:40uL];

When a separated portion is used only as the source of one transfer, write the selection directly on the source container:

text
waste << [sample.partition(magnetic_program(duration = 5min))[1]:120uL];

source.partition(program)[i] uses the same two-slot separation semantics as sep(...), but it is not a group-producing operation. It is valid only inside the right-hand source list of <<. Use sep(...) when the separated slots need names, later reuse, or multiple downstream operations.

Separation Programs

sep(...) and source.partition(program)[i] accept mechanism-specific binary separation programs.

ProgramRequired fieldsOptional fieldsMeaning
centrifuge_program(...)drivekeep_sourceCentrifuge separation.
magnetic_program(...)noneduration, deviceMagnetic separation.
disrupt_program(...)nonedurationDisruption or lysis-oriented separation.
field_program(...)fielddurationField-driven separation.
filtration_program(...)membrane, drivenoneFiltration separation.
phase_partition_program(...)solventnonePhase partition.
precipitation_program(...)reagentdurationPrecipitation.

centrifuge_program(...) does not take duration. To express "centrifuge for 5 min at 4C", put the sep(...) inside an environment block:

text
with env(thermal = 4C, duration = 5min) {
    let g = sep(sample = lysate, program = centrifuge_program(drive = 12000g));
}

Slot Meaning

The two slots have stable meanings determined by the program.

Programgroup[0]group[1]
centrifuge_programsupernatantpellet
magnetic_programboundflowthrough
disrupt_programlysatedebris_or_residue
field_programtarget_band_fractionnon_target_fraction
filtration_programfiltrateretentate
phase_partition_programtarget_phaseother_phase
precipitation_programprecipitatesupernatant

For source-local selection, the index has the same meaning: sample.partition(program)[0] selects the slot described in the group[0] column, and sample.partition(program)[1] selects the slot described in the group[1] column.

Material Partition Estimates

Runtime material compute estimates how much tracked content moves into each slot. This estimate is bookkeeping for protocol execution, not a scientific prediction.

Supported content classes use one of three ratio shapes:

RatioMeaning
0.99 / 0.01Near-complete separation into one slot.
0.95 / 0.05Strong enrichment with a small carryover.
0.50 / 0.50Conservative fallback when Culsma cannot infer a better partition.

Unsupported, unknown, compatibility-normalized, or composite content can still run. In those cases the runtime uses the conservative 0.50 / 0.50 fallback and emits MAT_CONTENT_PARTITION_FALLBACK.

keep_source

keep_source is only for centrifuge_program(...).

text
let g = sep(
    sample = lysate,
    program = centrifuge_program(drive = 12000g, keep_source = pellet)
);

keep_source = supernatant reuses the input container for group[0]. keep_source = pellet reuses the input container for group[1].

If keep_source is omitted, both slots are new containers.

frac(...)

frac(...) creates an ordered fraction group.

text
let fg = frac(
    sample = tube,
    program = density_gradient_program(axis = "density", order = "top_to_bottom", bins = 8)
);

The result is a fraction_group. Access slots with fg[0], fg[1], and so on.

Fractionation Programs

ProgramRequired fieldsMeaning
density_gradient_program(...)axis, order, binsDensity or layer-based fractionation.
chromatography_program(...)axis, order, binsRetention-order fractionation.

Index Rules

Group indexes are zero-based.

  • sep_container_group supports only group[0] and group[1].
  • source.partition(program)[i] supports only static indexes 0 and 1.
  • fraction_group[i] must be within 0 <= i < bins when bins is known.
  • Slices, multidimensional indexes, and dynamic index semantics are not part of this authoring surface.

Released under the Apache-2.0 license.