docs: def asarray(self, key=None, series=None, out=None, validate=True,
                  maxworkers=None):
          """Return image data from selected TIFF page(s) as numpy array.
  
          By default, the data from the first series is returned.
  
          Parameters
          ----------
          key : int, slice, or sequence of indices
              Defines which pages to return as array.
              If None (default), data from a series (default 0) is returned.
              If not None, data from the specified pages in the whole file
              (if 'series' is None) or a specified series are returned as a
              stacked array.
              Requesting an array from multiple pages that are not compatible
              wrt. shape, dtype, compression etc is undefined, i.e. may crash
              or return incorrect values.
          series : int or TiffPageSeries
              Defines which series of pages to return as array.
          out : numpy.ndarray, str, or file-like object
              Buffer where image data will be saved.
              If None (default), a new array will be created.
              If numpy.ndarray, a writable array of compatible dtype and shape.
              If 'memmap', directly memory-map the image data in the TIFF file
              if possible; else create a memory-mapped array in a temporary file.
              If str or open file, the file name or file object used to
              create a memory-map to an array stored in a binary file on disk.
          validate : bool
              If True (default), validate various tags.
              Passed to TiffPage.asarray().
          maxworkers : int or None
              Maximum number of threads to concurrently get data from pages
              or tiles. If None (default), mutli-threading is enabled if data
              are compressed. If 0, up to half the CPU cores are used.
              If 1, mutli-threading is disabled.
              Reading data from file is limited to a single thread.
              Using multiple threads can significantly speed up this function
              if the bottleneck is decoding compressed data, e.g. in case of
              large LZW compressed LSM files or JPEG compressed tiled slides.
              If the bottleneck is I/O or pure Python code, using multiple
              threads might be detrimental.
  
          Returns
          -------
          numpy.ndarray
              Image data from the specified pages.
              See the TiffPage.asarray function for operations that are
              applied (or not) to the raw data stored in the file.
  
          """
          if not self.pages:
              return numpy.array([])
          if key is None and series is None:
              series = 0
          if series is None:
              pages = self.pages
          else:
              try:
                  series = self.series[series]
              except (KeyError, TypeError):
                  pass
              pages = series.pages
  
          if key is None:
              pass
          elif series is None:
              pages = self.pages._getlist(key)
          elif isinstance(key, inttypes):
              pages = [pages[key]]
          elif isinstance(key, slice):
              pages = pages[key]
          elif isinstance(key, Iterable):
              pages = [pages[k] for k in key]
          else:
              raise TypeError('key must be an int, slice, or sequence')
  
          if not pages:
              raise ValueError('no pages selected')
  
          if key is None and series and series.offset:
              typecode = self.byteorder + series.dtype.char
              if pages[0].is_memmappable and (isinstance(out, str) and
                                              out == 'memmap'):
                  # direct mapping
                  result = self.filehandle.memmap_array(
                      typecode, series.shape, series.offset)
              else:
                  # read into output
                  if out is not None:
                      out = create_output(out, series.shape, series.dtype)
                  self.filehandle.seek(series.offset)
                  result = self.filehandle.read_array(
                      typecode, product(series.shape), out=out)
          elif len(pages) == 1:
              result = pages[0].asarray(out=out, validate=validate,
                                        maxworkers=maxworkers)
          else:
              result = stack_pages(pages, out=out, maxworkers=maxworkers)
  
          if result is None:
              return None
  
          if key is None:
              try:
                  result.shape = series.shape
              except ValueError:
                  try:
                      log.warning('TiffFile.asarray: failed to reshape %s to %s',
                                  result.shape, series.shape)
                      # try series of expected shapes
                      result.shape = (-1,) + series.shape
                  except ValueError:
                      # revert to generic shape
                      result.shape = (-1,) + pages[0].shape
          elif len(pages) == 1:
              result.shape = pages[0].shape
          else:
              result.shape = (-1,) + pages[0].shape
          return result