Skip to content

y5gfunc.expr.emulator

emulator

Classes:

Name Description
ConstantValues

Functions:

Name Description
emulate_expr

Emulate Akarin.Expr with the given constants, clip values and properties.

ConstantValues dataclass

ConstantValues(pi: float = pi, N: Optional[int] = None, X: Optional[int] = None, Y: Optional[int] = None, width: Optional[int] = None, height: Optional[int] = None)

Attributes:

Name Type Description
pi float
N Optional[int]
X Optional[int]
Y Optional[int]
width Optional[int]
height Optional[int]

pi class-attribute instance-attribute

pi: float = pi

N class-attribute instance-attribute

N: Optional[int] = None

X class-attribute instance-attribute

X: Optional[int] = None

Y class-attribute instance-attribute

Y: Optional[int] = None

width class-attribute instance-attribute

width: Optional[int] = None

height class-attribute instance-attribute

height: Optional[int] = None

emulate_expr

Emulate Akarin.Expr with the given constants, clip values and properties.

Parameters:

Name Type Description Default

expr

str

The expression to emulate.

required

constants

ConstantValues

An object containing constant values (N, X, Y, width, height, pi).

ConstantValues()

clip_value

Optional[dict[str, float]]

The values of the clips. (e.g. {"src0": 1.0, "src1": 2.0})

None

clip_prop

Optional[dict[str, list[tuple[str, float]]]]

The properties of the clips. (e.g. {"src0": [("prop1", 1234), ("prop2", 4567.8)], "src1": [("yajyuu_senpai", 114514)]})

None

Returns:

Type Description
float

The result of the expression.

Raises:

Type Description
ValueError

If the expression is invalid or if a clip or property is not found.

Source code in y5gfunc/expr/emulator.py
def emulate_expr(
    expr: str,
    constants: ConstantValues = ConstantValues(),
    clip_value: Optional[dict[str, float]] = None,
    clip_prop: Optional[dict[str, list[tuple[str, float]]]] = None,
) -> float:
    """
    Emulate Akarin.Expr with the given constants, clip values and properties.

    Args:
        expr: The expression to emulate.
        constants: An object containing constant values (N, X, Y, width, height, pi).
        clip_value: The values of the clips. (e.g. {"src0": 1.0, "src1": 2.0})
        clip_prop: The properties of the clips. (e.g. {"src0": [("prop1", 1234), ("prop2", 4567.8)], "src1": [("yajyuu_senpai", 114514)]})

    Returns:
        The result of the expression.

    Raises:
        ValueError: If the expression is invalid or if a clip or property is not found.
    """
    clip_value = clip_value or {}
    clip_prop = clip_prop or {}

    all_clip_names = list(clip_value.keys()) + list(clip_prop.keys())
    for name in all_clip_names:
        if not (is_clip_postfix(name) and name.startswith("src")):
            raise ValueError(f"emulate_expr: Invalid clip name provided: '{name}'")

    constant_values_dict = asdict(constants)

    expr = optimize_akarin_expr(expr)
    infix_expr = postfix2infix(expr)
    expanded_expr = infix2postfix(infix_expr)
    tokens = tokenize_expr(expanded_expr)

    for i, token in enumerate(tokens):
        if is_clip_postfix(token):
            if token in clip_value:
                value = clip_value[token]
                tokens[i] = str(value)
            else:
                raise ValueError(
                    f"emulate_expr: Clip '{token}' not found in provided values or properties."
                )
        elif _FRAME_PROP_PATTERN.match(token):
            clip_name, prop_name = token.split(".")
            found_prop_val = False
            for clip_nm, props in clip_prop.items():
                if clip_nm == clip_name:
                    for prop in props:
                        if prop[0] == prop_name:
                            if not found_prop_val:
                                found_prop_val = True
                                tokens[i] = str(prop[1])
                            else:
                                raise ValueError(
                                    f"emulate_expr: Duplicate property '{prop_name}' found for clip '{clip_name}'."
                                )
            if not found_prop_val:
                raise ValueError(
                    f"emulate_expr: Property '{prop_name}' not found for clip '{clip_name}'."
                )
        elif token in {"pi", "N", "X", "Y", "width", "height"}:
            if token in constant_values_dict:
                tokens[i] = str(constant_values_dict[token])
            else:
                raise ValueError(
                    f"emulate_expr: Constant '{token}' not found in provided constants."
                )

    try:
        ret = float(optimize_akarin_expr(" ".join(tokens)))
    except Exception as e:
        raise ValueError(
            f"emulate_expr: Error occurred while optimizing expression: {e}"
        )

    return ret