class_docstr: Organize Renderers for ``pyvista.Plotter``.
  
  Parameters
  ----------
  plotter : str
      The PyVista plotter.
  
  shape : tuple[int], optional
      The initial shape of the PyVista plotter, (rows, columns).
  
  splitting_position : float, optional
      The position to place the splitting line between plots.
  
  row_weights : sequence, optional
      The weights of the rows when the plot window is resized.
  
  col_weights : sequence, optional
      The weights of the columns when the plot window is resized.
  
  groups : list, optional
      A list of sequences that defines the grouping of the sub-datasets.
  
  border : bool, optional
      Whether or not a border should be added around each subplot.
  
  border_color : str, optional
      The color of the border around each subplot.
  
  border_width : float, optional
      The width of the border around each subplot.
class_docstr_tok: ["Organize","Renderers","for","``","pyvista.Plotter","``",".","Parameters","--","--","--","--","--","plotter",":","str","The","PyVista","plotter",".","shape",":","tuple","[","int","]",",","optional","The","initial","shape","of","the","PyVista","plotter",",","(","rows",",","columns",")",".","splitting_position",":","float",",","optional","The","position","to","place","the","splitting","line","between","plots",".","row_weights",":","sequence",",","optional","The","weights","of","the","rows","when","the","plot","window","is","resized",".","col_weights",":","sequence",",","optional","The","weights","of","the","columns","when","the","plot","window","is","resized",".","groups",":","list",",","optional","A","list","of","sequences","that","defines","the","grouping","of","the","sub-datasets",".","border",":","bool",",","optional","Whether","or","not","a","border","should","be","added","around","each","subplot",".","border_color",":","str",",","optional","The","color","of","the","border","around","each","subplot",".","border_width",":","float",",","optional","The","width","of","the","border","around","each","subplot","."]
docstr: Initialize renderers.
docstr_tok: ["Initialize","renderers","."]
code: def __init__(
      self,
      plotter,
      shape=(1, 1),
      splitting_position=None,
      row_weights=None,
      col_weights=None,
      groups=None,
      border=None,
      border_color="k",
      border_width=2.0,
  ):
      """Initialize renderers."""
      self._active_index = 0  # index of the active renderer
      self._plotter = proxy(plotter)
      self._renderers = []
      self._shadow_renderer = None
  
      # by default add border for multiple plots
      if border is None:
          if shape != (1, 1):
              border = True
          else:
              border = False
  
      self.groups = np.empty((0, 4), dtype=int)
  
      if isinstance(shape, str):
          if "|" in shape:
              n = int(shape.split("|")[0])
              m = int(shape.split("|")[1])
              rangen = reversed(range(n))
              rangem = reversed(range(m))
          else:
              m = int(shape.split("/")[0])
              n = int(shape.split("/")[1])
              rangen = range(n)
              rangem = range(m)
  
          if splitting_position is None:
              splitting_position = (
                  pyvista.global_theme.multi_rendering_splitting_position
              )
  
          if splitting_position is None:
              if n >= m:
                  xsplit = m / (n + m)
              else:
                  xsplit = 1 - n / (n + m)
          else:
              xsplit = splitting_position
  
          for i in rangen:
              arenderer = Renderer(
                  self._plotter, border, border_color, border_width
              )
              if "|" in shape:
                  arenderer.SetViewport(0, i / n, xsplit, (i + 1) / n)
              else:
                  arenderer.SetViewport(i / n, 0, (i + 1) / n, xsplit)
              self._renderers.append(arenderer)
          for i in rangem:
              arenderer = Renderer(
                  self._plotter, border, border_color, border_width
              )
              if "|" in shape:
                  arenderer.SetViewport(xsplit, i / m, 1, (i + 1) / m)
              else:
                  arenderer.SetViewport(i / m, xsplit, (i + 1) / m, 1)
              self._renderers.append(arenderer)
  
          self._shape = (n + m,)
          self._render_idxs = np.arange(n + m)
  
      else:
          if not isinstance(
              shape, (np.ndarray, collections.abc.Sequence)
          ):
              raise TypeError(
                  '"shape" should be a list, tuple or string descriptor'
              )
          if len(shape) != 2:
              raise ValueError('"shape" must have length 2.')
          shape = np.asarray(shape)
          if (
              not np.issubdtype(shape.dtype, np.integer)
              or (shape <= 0).any()
          ):
              raise ValueError(
                  '"shape" must contain only positive integers.'
              )
          # always assign shape as a tuple
          self._shape = tuple(shape)
          self._render_idxs = np.empty(self._shape, dtype=int)
          # Check if row and col weights correspond to given shape,
          # or initialize them to defaults (equally weighted).
  
          # and convert to normalized offsets
          if row_weights is None:
              row_weights = np.ones(shape[0])
          if col_weights is None:
              col_weights = np.ones(shape[1])
  
          # also make flattening and abs explicit
          row_weights = np.abs(np.asanyarray(row_weights).ravel())
          col_weights = np.abs(np.asanyarray(col_weights).ravel())
          if row_weights.size != shape[0]:
              raise ValueError(
                  f'"row_weights" must have {shape[0]} items '
                  f"for {shape[0]} rows of subplots, not "
                  f"{row_weights.size}."
              )
          if col_weights.size != shape[1]:
              raise ValueError(
                  f'"col_weights" must have {shape[1]} items '
                  f"for {shape[1]} columns of subplots, not "
                  f"{col_weights.size}."
              )
          row_off = np.cumsum(row_weights) / np.sum(row_weights)
          row_off = 1 - np.concatenate(([0], row_off))
          col_off = np.cumsum(col_weights) / np.sum(col_weights)
          col_off = np.concatenate(([0], col_off))
  
          # Check and convert groups to internal format (Nx4 matrix
          # where every row contains the row and col index of the
          # top left cell)
  
          if groups is not None:
              if not isinstance(groups, collections.abc.Sequence):
                  raise TypeError(
                      f'"groups" should be a list or tuple, not {type(groups).__name__}.'
                  )
              for group in groups:
                  if not isinstance(group, collections.abc.Sequence):
                      raise TypeError(
                          "Each group entry should be a list or "
                          f"tuple, not {type(group).__name__}."
                      )
                  if len(group) != 2:
                      raise ValueError(
                          "Each group entry must have length 2."
                      )
  
                  rows = group[0]
                  if isinstance(rows, slice):
                      rows = np.arange(self.shape[0], dtype=int)[rows]
                  cols = group[1]
                  if isinstance(cols, slice):
                      cols = np.arange(self.shape[1], dtype=int)[cols]
                  # Get the normalized group, i.e. extract top left corner
                  # and bottom right corner from the given rows and cols
                  norm_group = [
                      np.min(rows),
                      np.min(cols),
                      np.max(rows),
                      np.max(cols),
                  ]
                  # Check for overlap with already defined groups:
                  for i, j in product(
                      range(norm_group[0], norm_group[2] + 1),
                      range(norm_group[1], norm_group[3] + 1),
                  ):
                      if self.loc_to_group((i, j)) is not None:
                          raise ValueError(
                              f"Groups cannot overlap. Overlap found at position {(i, j)}."
                          )
                  self.groups = np.concatenate(
                      (self.groups, np.array([norm_group], dtype=int)),
                      axis=0,
                  )
          # Create subplot renderers
          for row, col in product(range(shape[0]), range(shape[1])):
              group = self.loc_to_group((row, col))
              nb_rows = None
              nb_cols = None
              if group is not None:
                  if (
                      row == self.groups[group, 0]
                      and col == self.groups[group, 1]
                  ):
                      # Only add renderer for first location of the group
                      nb_rows = (
                          1
                          + self.groups[group, 2]
                          - self.groups[group, 0]
                      )
                      nb_cols = (
                          1
                          + self.groups[group, 3]
                          - self.groups[group, 1]
                      )
              else:
                  nb_rows = 1
                  nb_cols = 1
              if nb_rows is not None:
                  renderer = Renderer(
                      self._plotter, border, border_color, border_width
                  )
                  x0 = col_off[col]
                  y0 = row_off[row + nb_rows]
                  x1 = col_off[col + nb_cols]
                  y1 = row_off[row]
                  renderer.SetViewport(x0, y0, x1, y1)
                  self._render_idxs[row, col] = len(self)
                  self._renderers.append(renderer)
              else:
                  self._render_idxs[row, col] = self._render_idxs[
                      self.groups[group, 0], self.groups[group, 1]
                  ]
  
      # each render will also have an associated background renderer
      self._background_renderers = [None for _ in range(len(self))]
  
      # create a shadow renderer that lives on top of all others
      self._shadow_renderer = Renderer(
          self._plotter, border, border_color, border_width
      )
      self._shadow_renderer.SetViewport(0, 0, 1, 1)
      self._shadow_renderer.SetDraw(False)
  
imports: import collections
  from itertools import product
  from weakref import proxy
  import numpy
  import pyvista
  from .background_renderer import BackgroundRenderer
  from .renderer import Renderer
label_desc: Use image node_id 1 to create a new Renderers object  with example: obj = Renderers(plotter, shape, splitting_position, row_weights, col_weights, groups, border, border_color, border_width)