docstr: :param pattern: example 'b t c <- b hsel wsel c, [hsel, wsel] b t'
docstr_tok: [":","param","pattern",":","example","'","b","t","c","<","-","b","hsel","wsel","c",",","[","hsel",",","wsel","]","b","t","'"]
code: def __init__(self, pattern: str):
      """
      :param pattern: example 'b t c <- b hsel wsel c, [hsel, wsel] b t'
      """
      self.pattern = pattern
      left, right = pattern.split("<-")
      arg_split = right.index(",")
      arr_pattern, ind_pattern = (
          right[:arg_split],
          right[arg_split + 1 :],
      )
      ind_pattern = ind_pattern.strip()
      # print(
      #     arr_pattern, '\n',
      #     ind_pattern,
      # )
      assert ind_pattern.startswith(
          "["
      ), "composition axis should go first in indexer (second argument) [h w] i j k"
      composition_start = ind_pattern.index("[")
      composition_end = ind_pattern.index("]")
      composition = ind_pattern[composition_start + 1 : composition_end]
      ind_other_axes = ind_pattern[composition_end + 1 :]
  
      self.result_axes_names = left.split()
      self.array_axes_names = arr_pattern.split()
      self.indexing_axes_names = [
          x.strip() for x in composition.split(",")
      ]
      self.indexer_other_axes_names = ind_other_axes.split()
  
      for group_name, group in [
          ("result", self.result_axes_names),
          ("array", self.array_axes_names),
          (
              "indexer",
              self.indexing_axes_names + self.indexer_other_axes_names,
          ),
      ]:
          if len(set(group)) != len(group):
              # need more verbosity, which axis, raise
              raise EinopsError(
                  f"{group_name} pattern ({group}) contains a duplicated axis"
              )
  
      axis_groups = [
          self.result_axes_names,
          self.array_axes_names,
          self.indexing_axes_names,
          self.indexer_other_axes_names,
      ]
  
      all_axes = set()
      for group in axis_groups:
          all_axes.update(group)
  
      self.indexer_axes = []
      self.batch_axes = []
      self.result_and_index_axes = []
      self.result_and_array_axes = []
  
      for axis in all_axes:
          presence = tuple(axis in g for g in axis_groups)
          # want match-case here. sweet dreams
          if presence == (False, True, True, False):
              self.indexer_axes.append(axis)
          elif presence[2]:
              raise EinopsError(
                  f"Wrong usage of indexer variable {axis}"
              )
          elif presence == (True, True, False, True):
              self.batch_axes.append(axis)
          elif presence == (True, False, False, True):
              self.result_and_index_axes.append(axis)
          elif presence == (True, True, False, False):
              self.result_and_array_axes.append(axis)
          else:
              # TODO better categorization of wrong usage patterns
              raise EinopsError(
                  f"{axis} is used incorrectly in {pattern}"
              )
  
      assert set(self.indexer_axes) == set(self.indexing_axes_names)
      # order of these variables matters, since we can't lose mapping here
      self.indexer_axes = self.indexing_axes_names
  
      self.array_composition = CompositionDecomposition(
          decomposed_shape=self.array_axes_names,
          composed_shape=[
              self.batch_axes + self.indexer_axes,
              self.result_and_array_axes,
          ],
      )
  
      self.index_composition = CompositionDecomposition(
          decomposed_shape=self.indexer_other_axes_names,
          # single axis after composition
          composed_shape=[self.batch_axes + self.result_and_index_axes],
      )
  
      self.result_composition = CompositionDecomposition(
          decomposed_shape=self.result_axes_names,
          composed_shape=[
              self.batch_axes + self.result_and_index_axes,
              self.result_and_array_axes,
          ],
      )
  
file_path: einops/einops/experimental/indexing.py
imports: from typing import List, Union, TypeVar, Tuple
  from einops import EinopsError
label_desc: Use image node_id 1 to create a new IndexingFormula object  with example: obj = IndexingFormula(pattern)