class_docstr: A reader for OME-NGFF files with the .zarr extension. Supports both 'normal' and
  'HCS' storage modes.
  
  OME-NGFF files below spec version 0.4 which are stored on S3/object storage
  should have the zarr.convenience.consolidate_metadata() function run on them
  to provide optimal performance over a network.
  
  Other non-OME .zarr format images may be readable, but are not strictly supported.
docstr: Read a single plane from the image file.
  :param c: read from this channel. `None` = read color image if multichannel
      or interleaved RGB.
  :param z: z-stack index
  :param t: time index
  :param series: series for ``.flex`` and similar multi-stack formats
  :param index: if `None`, fall back to ``zct``, otherwise load the indexed frame
  :param rescale: `True` to rescale the intensity scale to 0 and 1; `False` to
            return the raw values native to the file.
  :param xywh: a (x, y, w, h) tuple
  :param wants_max_intensity: if `False`, only return the image; if `True`,
            return a tuple of image and max intensity
  :param channel_names: provide the channel names for the OME metadata
docstr_tok: ["Read","a","single","plane","from","the","image","file",".",":","param","c",":","read","from","this","channel",".","`","None","`","=","read","color","image","if","multichannel","or","interleaved","RGB",".",":","param","z",":","z-stack","index",":","param","t",":","time","index",":","param","series",":","series","for","``",".flex","``","and","similar","multi-stack","formats",":","param","index",":","if","`","None","`",",","fall","back","to","``","zct","``",",","otherwise","load","the","indexed","frame",":","param","rescale",":","`","True","`","to","rescale","the","intensity","scale","to","0","and","1",";","`","False","`","to","return","the","raw","values","native","to","the","file",".",":","param","xywh",":","a","(","x",",","y",",","w",",","h",")","tuple",":","param","wants_max_intensity",":","if","`","False","`",",","only","return","the","image",";","if","`","True","`",",","return","a","tuple","of","image","and","max","intensity",":","param","channel_names",":","provide","the","channel","names","for","the","OME","metadata"]
code: def read(
      self,
      series=None,
      index=None,
      c=None,
      z=None,
      t=None,
      rescale=True,
      xywh=None,
      wants_max_intensity=False,
      channel_names=None,
  ):
      """Read a single plane from the image file.
      :param c: read from this channel. `None` = read color image if multichannel
          or interleaved RGB.
      :param z: z-stack index
      :param t: time index
      :param series: series for ``.flex`` and similar multi-stack formats
      :param index: if `None`, fall back to ``zct``, otherwise load the indexed frame
      :param rescale: `True` to rescale the intensity scale to 0 and 1; `False` to
                return the raw values native to the file.
      :param xywh: a (x, y, w, h) tuple
      :param wants_max_intensity: if `False`, only return the image; if `True`,
                return a tuple of image and max intensity
      :param channel_names: provide the channel names for the OME metadata
      """
      LOGGER.debug(
          f"Reading {c=}, {z=}, {t=}, {series=}, {index=}, {xywh=}"
      )
      c2 = None if c is None else c + 1
      z2 = None if z is None else z + 1
      t2 = None if t is None else t + 1
      if xywh is not None:
          x, y, w, h = xywh
          x = round(x)
          y = round(y)
          x2 = x + w
          y2 = y + h
      else:
          y, y2, x, x2 = None, None, None, None
      reader = self.get_reader()
      if series is None:
          series = 0
      if self._series_map is None:
          arrays = self.find_arrays(
              reader,
              multiscales=False,
              first_only=not self.planes_extracted,
          )
          self.build_series_map(arrays)
      if not self._series_map:
          raise IOError(
              "Zarr appears to contain no valid series. Unable to load data."
          )
      series_path, series_name = self._series_map[series]
      series_reader = reader[series_path]
      num_dimensions = len(series_reader.shape)
      # Todo: Handle V4 Axis object in .zattrs once it releases
      if num_dimensions == 5:
          image = series_reader[t:t2, c:c2, z:z2, y:y2, x:x2]
      elif num_dimensions == 4:
          image = series_reader[c:c2, z:z2, y:y2, x:x2]
      elif num_dimensions == 3:
          image = series_reader[z:z2, y:y2, x:x2]
      elif num_dimensions == 2:
          image = series_reader[y:y2, x:x2]
      else:
          raise NotImplementedError(
              f"Unsupported dimensionality: {num_dimensions}"
          )
      # Remove redundant axes
      image = numpy.squeeze(image)
      # C needs to be the last axis, but z should be first. Thank you CellProfiler.
      if len(image.shape) > 2 and z is not None:
          image = numpy.moveaxis(image, 0, -1)
      elif len(image.shape) > 3:
          image = numpy.moveaxis(image, 0, -1)
      scale = numpy.iinfo(image.dtype).max
      if rescale:
          image = image.astype(float) / scale
      if wants_max_intensity:
          if image.dtype in [numpy.int8, numpy.uint8]:
              scale = 255
          elif image.dtype in [numpy.int16, numpy.uint16]:
              scale = 65535
          elif image.dtype == numpy.int32:
              scale = 2**32 - 1
          elif image.dtype == numpy.uint32:
              scale = 2**32
          else:
              scale = 1
          return image, scale
      return image
  
imports: import numpy
  import zarr
  from ..constants.image import MD_SIZE_S, MD_SIZE_C, MD_SIZE_Z, MD_SIZE_T, MD_SIZE_Y, MD_SIZE_X, MD_SERIES_NAME
  from ..constants.reader import ZARR_FILETYPE
  from ..reader import Reader
  import os
  import re
  import logging
  from lxml import etree
label_desc: Use image node_id 5 for calling the NGFFReader obj's underlying member method code with example usage: obj.read(series, index, c, z, t, rescale, xywh, wants_max_intensity, channel_names) and returns: image, image,  scale