A component that computes something from a
run, such as a median over a scan or a
filtered copy of each frame, writes the result against the store the device
wrote. The acquisition belongs to the service and its device (ADR
0013),
so a derived product is the one
thing redsun writes. Derived products
says why a product is handed over rather than carried by a
document.
Step through what the component, its writer and the store do during one run:
A derived product through one run
The component declares the product in its constructor, then forwards each document of the run to its writer.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
The descriptor of the source gives the writer the frame's shape and dtype.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
The stream_resource of the source gives it the store the device writes to.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
A product computed frame by frame goes in with append, at each event.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
The first append or write opens a stream on the store, with every product of that store known by then.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
A product computed whole goes in with write, when the component handles the run's stop document.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
Then the writer sees the stop document, closes the stream and writes the metadata.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
your componentWriterthe device's storeThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.constructor: derive(product, source=...)descriptor of source:frame shape and dtypestream_resource of source:the storeevent: append(product, frames)first append or write: open a streamwith every product of the storestop: write(product, data)stop of the run: close the stream,write the metadataThe store the stream_resource document names, written by the device during the run. Beside an OME-Zarr image, the product gets a store of its own instead.
The zarr extra brings acquire-zarr, which every product needs. The
ome-zarr extra also brings ome-writers[acquire-zarr], which you need only to
write beside an OME-Zarr image.
Without acquire-zarr, importing redsun.writers raises ImportError naming
the extra. Without ome-writers, the first product placed beside an image
raises it.
sources holds the data keys to compute
from, and it comes from the session file like any other argument of a
component.
derive takes the layout and the store from the run's documents. A key described as external: STREAM: leads its shape with
the frames per event, which derive drops. For a product the run says nothing
about, declare gives both up front:
The writer learns about the run from its documents, so forward each one after
the component's own dispatch. That way the writer sees stop only after the
component has written what it computes there:
Use append for a product you write as the run goes, one frame or a stack of
frames at a time, and write for one you compute at the end and hand over
whole. Below, source is one of the data keys, and filtered and median are
the arrays the component computed for it:
The store's stream closes at the stop of the run that named the store. A
run nested inside another sees what the outer run
declared, so a product computed at the nested run's stop can go to the outer
run's store.
A product declared after the stream opens
The writer refuses a product declared once its store's stream is open, with
a WriterError naming it. Declare every product in the constructor.
shutdown closes whatever a session that ended mid-run left open, so the store
stays readable.
The stream_resource document names the format and the store, and the writer
reads the store's root to decide where the product goes. redsun.writers
exports the two mimetypes it knows as ZARR and OME_ZARR, for a device that
writes either into its documents:
Mimetype
Store root
Product goes
write returns
application/x-zarr
a plain group
a key of the same store
the store's URI
application/x-ome-zarr
a plain group
a key of the same store, with NGFF metadata of its own
the store's URI
application/x-ome-zarr
an image, a plate, a bioformats2raw layout
a store of its own beside it, named <store>_<data_key>.ome.zarr
the new store's URI
Adding a key to a root that carries OME-Zarr metadata drops it, which is why
the product goes beside such a root. A store of its own is written all at once,
because ome-writers allocates every frame at open, so append to it is
refused and write finishes it at once. If a stream_resource has a mimetype
the writer doesn't know, the writer logs it once and skips the product for that
run.
Two mappings land on the product's own group, never on the store's root, which
a stream closing on the store rewrites. One is the metadata you give to
write, as given, and the other is a redsun mapping the writer fills from the
run.
Key
Value
run_start
the uid of the run, null for a product written outside one
source
the data key a derived product was laid out and stored as
A writer registers nothing, so a product that belongs in a catalog has to be
put there by the same component. Writing and registering are separate choices.