Skip to content

XYAny

Documentation

  • Class name: XYAny
  • Category: List Stuff
  • Output node: False

The XYAny node is designed to generate combinations of X and Y values, optionally incorporating a third dimension, Z, to extend these combinations. It facilitates the creation and labeling of these combinations, providing fallback labels and the ability to specify custom labels. This node is particularly useful for data manipulation and preparation tasks where the relationships or interactions between different sets of data points need to be explored or visualized.

Input types

Required

  • X
    • The primary set of values to be combined. Acts as one axis in the generation of value pairs.
    • Comfy dtype: *
    • Python dtype: List[Any]
  • Y
    • The secondary set of values to be combined with the X values. Acts as the other axis in the generation of value pairs.
    • Comfy dtype: *
    • Python dtype: List[Any]
  • X_Label_Fallback
    • Fallback labels for the X values, used when specific labels are not provided. Ensures that each X value has an associated label.
    • Comfy dtype: COMBO[STRING]
    • Python dtype: List[str]
  • Y_Label_Fallback
    • Fallback labels for the Y values, used when specific labels are not provided. Ensures that each Y value has an associated label.
    • Comfy dtype: COMBO[STRING]
    • Python dtype: List[str]
  • Z_Label_Fallback
    • Fallback labels for the Z values, used when specific labels are not provided. This allows for a third dimension of data to be labeled.
    • Comfy dtype: COMBO[STRING]
    • Python dtype: List[str]

Optional

  • Z
    • An optional third set of values to be combined with the X and Y values, adding a third dimension to the combinations.
    • Comfy dtype: *
    • Python dtype: Optional[List[Any]]
  • X_Labels
    • Custom labels for the X values, overriding the fallback labels if provided.
    • Comfy dtype: *
    • Python dtype: Optional[List[Any]]
  • Y_Labels
    • Custom labels for the Y values, overriding the fallback labels if provided.
    • Comfy dtype: *
    • Python dtype: Optional[List[Any]]
  • Z_Labels
    • Custom labels for the Z values, overriding the fallback labels if provided.
    • Comfy dtype: *
    • Python dtype: Optional[List[Any]]

Output types

  • X Values
    • Comfy dtype: *
    • The combined X values resulting from the combinations generated by the node.
    • Python dtype: List[Any]
  • X Labels
    • Comfy dtype: STRING
    • The labels associated with the combined X values.
    • Python dtype: List[str]
  • Y Values
    • Comfy dtype: *
    • The combined Y values resulting from the combinations generated by the node.
    • Python dtype: List[Any]
  • Y Labels
    • Comfy dtype: STRING
    • The labels associated with the combined Y values.
    • Python dtype: List[str]
  • Z Values
    • Comfy dtype: *
    • The combined Z values resulting from the combinations generated by the node, if Z values were provided.
    • Python dtype: List[Any]
  • Z Labels
    • Comfy dtype: STRING
    • The labels associated with the combined Z values, if Z values were provided.
    • Python dtype: List[str]
  • Total Images
    • Comfy dtype: INT
    • The total number of combinations generated by the node.
    • Python dtype: int
  • Split Every
    • Comfy dtype: INT
    • The interval at which the combinations are split, based on the length of the Y values.
    • Python dtype: int

Usage tips

  • Infra type: CPU
  • Common nodes: unknown

Source code

class UnzippedProductAny:
    def __init__(self) -> None:
        pass

    @classmethod
    def INPUT_TYPES(s) -> Dict[str, Dict[str, Any]]:
        return {
            "required": {
                "X": (ANY, {}),
                "Y": (ANY, {}),
                "X_Label_Fallback": (["str()", "Numbers"], {"default": "str()"}),
                "Y_Label_Fallback": (["str()", "Numbers"], {"default": "str()"}),
                "Z_Label_Fallback": (["str()", "Numbers"], {"default": "str()"}),
            },
            "optional": {
                "Z": (ANY, {}),
                "X_Labels": (ANY, {}),
                "Y_Labels": (ANY, {}),
                "Z_Labels": (ANY, {}),
            },
        }

    RETURN_NAMES, RETURN_TYPES = zip(*{
        "X Values": ANY,
        "X Labels": "STRING",
        "Y Values": ANY,
        "Y Labels": "STRING",
        "Z Values": ANY,
        "Z Labels": "STRING",
        "Total Images": "INT",
        "Split Every": "INT",
    }.items())

    OUTPUT_IS_LIST = (True, True, True, True, True, True, False, False)
    INPUT_IS_LIST = True
    FUNCTION = "to_xy"

    CATEGORY = "List Stuff"

    def to_xy(
        self,
        X: List[Any],
        Y: List[Any],
        X_Label_Fallback: List[str],
        Y_Label_Fallback: List[str],
        Z_Label_Fallback: List[str],
        Z: Optional[List[Any]] = None,
        X_Labels: Optional[List[Any]] = None,
        Y_Labels: Optional[List[Any]] = None,
        Z_Labels: Optional[List[Any]] = None,
    ) -> Tuple[List[Any], List[str], List[Any], List[str], List[Any], List[str], int, int]:
        # region Validation
        if len(X_Label_Fallback) != 1:
            raise Exception("X_Label_Fallback must be a single value")
        if len(Y_Label_Fallback) != 1:
            raise Exception("Y_Label_Fallback must be a single value")
        if len(Z_Label_Fallback) != 1:
            raise Exception("Z_Label_Fallback must be a single value")

        if Z_Labels is not None and Z is None:
            raise Exception("Z_Labels must be None if Z is None")

        # region Labels
        get_x_fallback_labels: Callable[[Any], List[str]]
        if X_Label_Fallback[0] == "str()":
            get_x_fallback_labels = lambda x: [str(i) for i in x]
        else:
            get_x_fallback_labels = lambda x: [str(i) for i in range(len(x))]

        get_y_fallback_labels: Callable[[Any], List[str]]
        if Y_Label_Fallback[0] == "str()":
            get_y_fallback_labels = lambda x: [str(i) for i in x]
        else:
            get_y_fallback_labels = lambda x: [str(i) for i in range(len(x))]

        get_z_fallback_labels: Callable[[Any], List[str]]
        if Z_Label_Fallback[0] == "str()":
            get_z_fallback_labels = lambda x: [str(i) for i in x]
        else:
            get_z_fallback_labels = lambda x: [str(i) for i in range(len(x))]

        if X_Labels is None:
            X_Labels = get_x_fallback_labels(X)
        if Y_Labels is None:
            Y_Labels = get_y_fallback_labels(Y)
        if Z_Labels is None and Z is not None:
            Z_Labels = get_z_fallback_labels(Z)
        # endregion

        xy_product = itertools.product(X, Y)
        X_out_tuple, Y_out_tuple = zip(*xy_product)
        X_out: List[str] = list(X_out_tuple)
        Y_out: List[str] = list(Y_out_tuple)

        Z_out = []
        if Z is not None:
            original_len = len(X_out)
            X_out = X_out * len(Z)
            Y_out = Y_out * len(Z)
            for z in Z:
                Z_out.extend([z] * original_len)


        if Z_Labels is None:
            Z_Labels = []

        return X_out, X_Labels, Y_out, Y_Labels, Z_out, Z_Labels, len(X_out), len(Y)