class_docstr: This class represents an image file
  
  A file is considered as a single URL.
  
  A single file can contain multiple planes.
  
  This class assists in extracting information about the contents of
  a single file.
code: def extract_planes(self, workspace=None):
      if self._extracted:
          return
      # Figure out the number of planes, indexes or series in the file.
      try:
          reader = self.get_reader()
      except:
          LOGGER.error(
              f"May not be an image: {self.url}", exc_info=True
          )
          self.metadata[MD_SIZE_S] = 0
          return
      meta_dict = reader.get_series_metadata()
      if meta_dict[MD_SIZE_S] == 0:
          LOGGER.error(
              f"File {self.filename} appears to contain no images."
          )
          self.metadata[MD_SIZE_S] = 0
          self.release_reader()
          return
      elif MD_SERIES_NAME not in meta_dict:
          meta_dict[MD_SERIES_NAME] = [""] * meta_dict[MD_SIZE_S]
      assert MD_SIZE_KEYS.issubset(
          meta_dict.keys()
      ), "Returned metadata keys are incomplete"
      self.metadata.update(meta_dict)
      for S, C, Z, T, Y, X, name in self.get_plane_iterator():
          self._plane_details.append(
              f"Series {S:>2}{f' ({name})' if name else ''}"
              f": {X:>5} x {Y:<5}, {C} Channels, {Z:>2} Planes, {T:>2} Timepoints"
          )
      if workspace is not None:
          metadata_array = numpy.transpose(
              [
                  self.metadata[MD_SIZE_C],
                  self.metadata[MD_SIZE_Z],
                  self.metadata[MD_SIZE_T],
                  self.metadata[MD_SIZE_Y],
                  self.metadata[MD_SIZE_X],
              ]
          )
          names_array = self.metadata[MD_SERIES_NAME]
          workspace.file_list.add_metadata(
              self.url, metadata_array.flatten(), names_array
          )
      self._extracted = True
      self.release_reader()
  
imports: import os
  import urllib.parse
  import urllib.request
  import logging
  from functools import cached_property
  import numpy
  from cellprofiler_core.constants.image import MD_SIZE_S, MD_SIZE_C, MD_SIZE_Z, MD_SIZE_T, MD_SIZE_Y, MD_SIZE_X, MD_SIZE_KEYS, MD_SERIES_NAME
  from cellprofiler_core.constants.modules.metadata import COL_PATH, COL_SERIES, COL_INDEX, COL_URL
  from cellprofiler_core.constants.measurement import RESERVED_METADATA_KEYS
  from cellprofiler_core.reader import get_image_reader, Reader
  from cellprofiler_core.utilities.image import url_to_modpath, is_file_url
label_desc: Use image node_id 6 for calling the ImageFile obj's underlying member method code with example usage: obj.extract_planes(workspace) without return types