docstr: Rough but surprisingly accurate plate detection.
  
  Just groups by the shape of the underlying distribution.  Will be wrong
  if there are two plates with the same shape.
  
  Returns
  -------
  dict
      Maps plate labels to the set of ``VarName``s inside the plate.
docstr_tok: ["Rough","but","surprisingly","accurate","plate","detection",".","Just","groups","by","the","shape","of","the","underlying","distribution",".","Will","be","wrong","if","there","are","two","plates","with","the","same","shape",".","Returns","--","--","--","-","dict","Maps","plate","labels","to","the","set","of","``","VarName","``","s","inside","the","plate","."]
code: def get_plates(
      self, var_names: Optional[Iterable[VarName]] = None
  ) -> Dict[str, Set[VarName]]:
      """Rough but surprisingly accurate plate detection.
  
      Just groups by the shape of the underlying distribution.  Will be wrong
      if there are two plates with the same shape.
  
      Returns
      -------
      dict
          Maps plate labels to the set of ``VarName``s inside the plate.
      """
      plates = defaultdict(set)
  
      # TODO: Evaluate all RV shapes and dim_length at once.
      #       This should help to find discrepancies, and
      #       avoids unnecessary function compiles for deetermining labels.
  
      for var_name in self.vars_to_plot(var_names):
          v = self.model[var_name]
          shape: Sequence[int] = fast_eval(v.shape)
          dim_labels = []
          if var_name in self.model.named_vars_to_dims:
              # The RV is associated with `dims` information.
              for d, dname in enumerate(
                  self.model.named_vars_to_dims[var_name]
              ):
                  if dname is None:
                      # Unnamed dimension in a `dims` tuple!
                      dlen = shape[d]
                      dname = f"{var_name}_dim{d}"
                  else:
                      dlen = fast_eval(self.model.dim_lengths[dname])
                  dim_labels.append(f"{dname} ({dlen})")
              plate_label = " x ".join(dim_labels)
          else:
              # The RV has no `dims` information.
              dim_labels = [str(x) for x in shape]
              plate_label = " x ".join(map(str, shape))
          plates[plate_label].add(var_name)
  
      return dict(plates)
  
imports: import warnings
  from collections import defaultdict
  from typing import Dict, Iterable, List, Optional, Sequence, Set
  from pytensor import function
  from pytensor.compile.sharedvalue import SharedVariable
  from pytensor.graph import Apply
  from pytensor.graph.basic import ancestors, walk
  from pytensor.scalar.basic import Cast
  from pytensor.tensor.elemwise import Elemwise
  from pytensor.tensor.random.op import RandomVariable
  from pytensor.tensor.shape import Shape
  from pytensor.tensor.variable import TensorConstant, TensorVariable
  import pymc
  from pymc.util import VarName, get_default_varnames, get_var_name
label_desc: Use image node_id 6 for calling the ModelGraph obj's underlying member method code with example usage: obj.get_plates(var_names) and returns: dict