<jupyter_start><jupyter_text>Basic zarr handling1. Open your OME-NGFF zarr and look at the info<jupyter_code>z = zarr.open('/projects/researchit/djme/zarr_dask_examples/zarrs/histopath_example.zarr', mode='r')
z.info<jupyter_output><empty_output><jupyter_text>2. Check the bioformats2raw layout version<jupyter_code>z.attrs['bioformats2raw.layout']<jupyter_output><empty_output><jupyter_text>3. This zarr was created from an NDPI file, which outputs three images, which is why there are three groups. Only the first image has the raw data we are looking for, so let's take a look at the info for that:<jupyter_code>z['0'].info<jupyter_output><empty_output><jupyter_text>4. This "image" is still considered a group, because zarrs produced by `bioformats2raw` are multiscale. Thus each of these ten arrays is a pyramid (resolution) level. The `0` array is full resolution, `1` is 1/2 scale along the x and y axes, `2` is 1/4 scale, and so on. Let's take a look at a few:<jupyter_code>z['0/0'].info  # Full resolution pyramid level
z['0/1'].info  # 1/2 scale along x and y
z['0/2'].info  # 1/4 scale along x and y<jupyter_output><empty_output><jupyter_text>5. Let's dive into the full resolution array:<jupyter_code>zim = z['0/0']
type(zim)
zim.shape
zim.chunks
zim.nchunks<jupyter_output><empty_output><jupyter_text>6. Slicing a zarr returns a numpy array<jupyter_code>zim[0,0,0,:50,:50]
type(zim[0,0,0,:50,:50])
plt.imshow(zim[0,0,0,10000:18000,16000:24000]);<jupyter_output><empty_output><jupyter_text>7. This is actually an RGB image. `matplotlib` can handle that, but we need to reshape<jupyter_code>rgb_zim = np.moveaxis(zim[0,:,0,10000:18000,16000:24000], 0, -1)
rgb_zim.shape
plt.imshow(rgb_zim);<jupyter_output><empty_output><jupyter_text>8. Precomputed pyramids are great for when you don't need full resolution data, e.g., if you want to take a look at a global view of the whole slide<jupyter_code>zim_small = z['0/7']  # remember that the second group in the path is pyramid level
zim_small.shape
zim_small_array = np.moveaxis(zim_small[0,:,0,:,:], 0, -1)
zim_small_array.shape
plt.imshow(zim_small_array);<jupyter_output><empty_output><jupyter_text>9. We can also load a zarr from object storage over the internet. Here is the same image loaded from some S3-compatible object storage. Note that we are specifying the full resolution image, not the top level zarr group:<jupyter_code>za = zarr.open('http://s3-far.jax.org/zarrtest/histopath_example.zarr/0/0', mode='r')
za.info<jupyter_output><empty_output><jupyter_text>10. This new zarr loaded over http can be used just like the one we loaded from the filesystem.<jupyter_code>plt.imshow(za[0,0,0,10000:18000,16000:24000]);<jupyter_output><empty_output><jupyter_text>Using OME-NGFF/zarr for exploring high content screening data 11. Plate data can also be converted to an OME-NGFF zarr! Like our slide scan example, plates are also zarr groups, with the top level group indicating row. In this example, we have 8 rows of wells:<jupyter_code>plate = zarr.open('/projects/researchit/djme/zarr_dask_examples/zarrs/plate_example.zarr/', mode='r')
plate.info<jupyter_output><empty_output><jupyter_text>12. And we have 12 columns of wells:<jupyter_code>plate['0'].info<jupyter_output><empty_output><jupyter_text>13. When selecting info for a specific well (i.e., specifying both row and column of the plate in the path), you find that the well itself is also a group. This grouping contains "fields", which are independent images taken of a single well. This well has 25 fields:<jupyter_code>plate['0/0'].info<jupyter_output><empty_output><jupyter_text>14. The next level down is your multiscale level, so selecting '0' for that will give you your image:<jupyter_code>plate['0/0/0/0'].info<jupyter_output><empty_output><jupyter_text>15. zarr groups give you useful iterators that can be used to loop over your data. Here is how you might loop over all of the fields in a well:<jupyter_code>_, axes = plt.subplots(nrows=5, ncols=5, figsize=(14, 14))

for field_index, field in plate['2/2'].groups():
    field_index = int(field_index)  # Because this starts as a string
    axes.flatten()[field_index].imshow(field['0'][0,0,0,:,:]);<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11261261261261261, 'fraction_numerical': 0.038643907064959696, 'mean_word_length': 6.2243150684931505, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '246785', 'license': 'MIT', 'n_tokens_mistral': 1604, 'n_tokens_neox': 1497, 'n_words': 448, 'path': 'tutorials/02_ome-zarr_basics.ipynb', 'repo_name': 'TheJacksonLaboratory/zarr_and_dask_demo', 'size': '4218'}