docs: def create_multi_output_factor(self, tool, source, splitting_node, sink):
          """
          Creates a multi-output factor.
          This takes a single node, applies a MultiOutputTool to create multiple nodes on a new plate
          Instantiates a single tool for all of the input plate values,
          and connects the source and sink nodes with that tool.
  
          Note that the tool parameters these are currently fixed over a plate. For parameters that vary over a plate,
          an extra input stream should be used
  
          :param tool: The tool to use. This is either an instantiated Tool object or a dict with "name" and "parameters"
          :param source: The source node
          :param splitting_node: The node over which to split
          :param sink: The sink node
          :return: The factor object
          :type tool: MultiOutputTool | dict
          :type source: Node | None
          :type sink: Node
          :rtype: Factor
          """
          if source and not isinstance(source, Node):
              raise ValueError("Expected Node, got {}".format(type(source)))
  
          if not isinstance(sink, Node):
              raise ValueError("Expected Node, got {}".format(type(sink)))
  
          # if isinstance(tool, dict):
          #     tool = self.channels.get_tool(**tool)
  
          if not isinstance(tool, MultiOutputTool):
              raise ValueError("Expected MultiOutputTool, got {}".format(type(tool)))
  
          # Check that the input_plate are compatible - note this is the opposite way round to a normal factor
          input_plates = source.plates if source else []
          output_plates = sink.plates
  
          if len(input_plates) > 1:
              raise NotImplementedError
  
          if len(output_plates) == 0:
              raise ValueError("No output plate found")
  
          if len(output_plates) == 1:
              if not self.check_multi_output_plate_compatibility(input_plates, output_plates[0]):
                  raise IncompatiblePlatesError("Parent plate does not match input plate")
  
              factor = MultiOutputFactor(tool=tool, source_node=source, splitting_node=splitting_node, sink_node=sink,
                                         input_plate=input_plates[0] if input_plates else None,
                                         output_plates=output_plates[0])
          else:
              # The output plates should be the same as the input plates, except for one
              # additional plate. Since we're currently only supporting one input plate,
              # we can safely assume that there is a single matching plate.
              # Finally, note that the output plate must either have no parents
              # (i.e. it is at the root of the tree), or the parent plate is somewhere
              # in the input plate's ancestry
              if len(output_plates) > 2:
                  raise NotImplementedError
              if len(input_plates) != 1:
                  raise IncompatiblePlatesError("Require an input plate to match all but one of the output plates")
              if output_plates[0] == input_plates[0]:
                  # Found a match, so the output plate should be the other plate
                  output_plate = output_plates[1]
              else:
                  if output_plates[1].plate_id != input_plates[0].plate_id:
                      raise IncompatiblePlatesError("Require an input plate to match all but one of the output plates")
                  output_plate = output_plates[0]
                  # Swap them round so the new plate is the last plate - this is required by the factor
                  output_plates[1], output_plates[0] = output_plates[0], output_plates[1]
  
              if not output_plate.is_root:
                  # We need to walk up the input plate's parent tree
                  match = False
                  parent = input_plates[0].parent
                  while parent is not None:
                      if parent.plate_id == output_plate.parent.plate_id:
                          match = True
                          break
                      parent = parent.parent
                  if not match:
                      raise IncompatiblePlatesError("Require an input plate to match all but one of the output plates")
  
              factor = MultiOutputFactor(
                  tool=tool, source_node=source, sink_node=sink,
                  splitting_node=splitting_node, input_plate=input_plates[0], output_plates=output_plates)
  
          self._add_factor(factor)
          return factor