High-content-screening plates¶
PlateWriter writes a plate as the plate/<row>/<column>/<field> layout defined by the OME-Zarr 0.5 spec. Each field of
view is an ordinary multiscale image written with Writer, so it accepts the same options.
import numpy as np
from ome_zarr_io import PlateWriter
units = {"y": "micrometer", "x": "micrometer"}
with PlateWriter(
"screen.ome.zarr",
rows=["A", "B"],
columns=["1", "2", "3"],
name="Screen 1",
acquisitions=[{"id": 0, "name": "t0"}], # optional
) as plate:
for row, column in [("A", "1"), ("A", "2"), ("B", "3")]:
for _ in range(2): # two fields of view per well
image = np.random.randint(0, 255, size=(2, 256, 256), dtype=np.uint8)
plate.add_field(
row, column, image, dims=["c", "y", "x"], axis_units=units,
channels=["DAPI", "GFP"], downscale_levels=2, acquisition=0,
)
Rows and columns are declared up front. Their order sets each well’s
rowIndexandcolumnIndex.add_fieldtakes the same keyword arguments asWriter(exceptoverwrite, which belongs to the plate). It creates the row and well groups as needed.field=sets the field index; by default the next free one is used.If you declare more than one acquisition, every
add_fieldcall must say which one it belongs to (acquisition=), as the spec requires.The well and plate metadata are rewritten after every field, so an interrupted run leaves a valid partial plate. The plate metadata first appears with the first field, because the spec requires at least one well.
By default every field must match the first one in dims, axes and channels. Pass
check_consistency=Falseto allow mixed fields.add_fieldreturns the field’sWriter, so you can attach labels withadd_labels.Leaving the
withblock validates the plate and all wells against the schemas. Withoutwith, callplate.close().overwrite=Truereplaces an existing plate.