---
title: utils
---

<div class="python-reference">
<a id="fastvideo.models.dits.matrixgame2.utils-functions"></a>
<a id="fastvideo.models.dits.matrixgame2.utils"></a>

<h2 id="fastvideo.models.dits.matrixgame2.utils.get_local_torch_device"><code>fastvideo.models.dits.matrixgame2.utils.get_local_torch_device</code></h2>
<pre class="doc-signature"><code>get_local_torch_device() -&gt; torch.device</code></pre>
<p>Return the torch device for the current rank.</p>
<h2 id="fastvideo.models.dits.matrixgame2.utils.retain_kv_with_sink"><code>fastvideo.models.dits.matrixgame2.utils.retain_kv_with_sink</code></h2>
<pre class="doc-signature"><code>retain_kv_with_sink(k: torch.Tensor, v: torch.Tensor, target_len: int, sink_size: int) -&gt; tuple&#91;torch.Tensor, torch.Tensor&#93;</code></pre>

<details><summary>Source</summary><pre><code>def retain_kv_with_sink(
    k: torch.Tensor,
    v: torch.Tensor,
    target_len: int,
    sink_size: int,
) -&gt; tuple&#91;torch.Tensor, torch.Tensor&#93;:
    if k.shape&#91;1&#93; &lt;= target_len or sink_size &lt;= 0:
        return k&#91;:, -target_len:&#93;, v&#91;:, -target_len:&#93;

    sink_len = min(int(sink_size), target_len, k.shape&#91;1&#93;)
    tail_len = target_len - sink_len
    sink_k = k&#91;:, :sink_len&#93;
    sink_v = v&#91;:, :sink_len&#93;
    if tail_len &lt;= 0:
        return sink_k, sink_v

    tail_k = k&#91;:, sink_len:&#93;&#91;:, -tail_len:&#93;
    tail_v = v&#91;:, sink_len:&#93;&#91;:, -tail_len:&#93;
    return torch.cat(&#91;sink_k, tail_k&#93;, dim=1), torch.cat(&#91;sink_v, tail_v&#93;, dim=1)</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.draw_rounded_rectangle"><code>fastvideo.models.dits.matrixgame2.utils.draw_rounded_rectangle</code></h2>
<pre class="doc-signature"><code>draw_rounded_rectangle(image: np.ndarray, top_left: tuple&#91;int, int&#93;, bottom_right: tuple&#91;int, int&#93;, color: tuple&#91;int, int, int&#93;, radius: int = 10, alpha: float = 0.5) -&gt; None</code></pre>

<details><summary>Source</summary><pre><code>def draw_rounded_rectangle(
    image: np.ndarray,
    top_left: tuple&#91;int, int&#93;,
    bottom_right: tuple&#91;int, int&#93;,
    color: tuple&#91;int, int, int&#93;,
    radius: int = 10,
    alpha: float = 0.5,
) -&gt; None:
    if not _require_cv2():
        return

    overlay = image.copy()
    x1, y1 = top_left
    x2, y2 = bottom_right

    cv2.rectangle(overlay, (x1 + radius, y1), (x2 - radius, y2), color, -1)
    cv2.rectangle(overlay, (x1, y1 + radius), (x2, y2 - radius), color, -1)
    cv2.ellipse(overlay, (x1 + radius, y1 + radius), (radius, radius), 180, 0, 90, color, -1)
    cv2.ellipse(overlay, (x2 - radius, y1 + radius), (radius, radius), 270, 0, 90, color, -1)
    cv2.ellipse(overlay, (x1 + radius, y2 - radius), (radius, radius), 90, 0, 90, color, -1)
    cv2.ellipse(overlay, (x2 - radius, y2 - radius), (radius, radius), 0, 0, 90, color, -1)
    cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0, image)</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.draw_keys_on_frame"><code>fastvideo.models.dits.matrixgame2.utils.draw_keys_on_frame</code></h2>
<pre class="doc-signature"><code>draw_keys_on_frame(frame: np.ndarray, keys: dict&#91;str, bool&#93;, key_size: tuple&#91;int, int&#93; = (30, 30), top_margin: int = 15) -&gt; None</code></pre>

<details><summary>Source</summary><pre><code>def draw_keys_on_frame(
        frame: np.ndarray,
        keys: dict&#91;str, bool&#93;,
        key_size: tuple&#91;int, int&#93; = (30, 30),
        top_margin: int = 15,
) -&gt; None:
    if not _require_cv2():
        return

    left_margin = 15
    gap = 3
    key_positions = &#123;
        &quot;W&quot;: (left_margin + key_size&#91;0&#93; + gap, top_margin),
        &quot;A&quot;: (left_margin, top_margin + key_size&#91;1&#93; + gap),
        &quot;S&quot;: (left_margin + key_size&#91;0&#93; + gap, top_margin + key_size&#91;1&#93; + gap),
        &quot;D&quot;: (
            left_margin + (key_size&#91;0&#93; + gap) * 2,
            top_margin + key_size&#91;1&#93; + gap,
        ),
    &#125;

    for key, (x, y) in key_positions.items():
        pressed = keys.get(key, False)
        color = (0, 255, 0) if pressed else (200, 200, 200)
        alpha = 0.8 if pressed else 0.5
        draw_rounded_rectangle(
            frame,
            (x, y),
            (x + key_size&#91;0&#93;, y + key_size&#91;1&#93;),
            color,
            radius=5,
            alpha=alpha,
        )
        text_size = cv2.getTextSize(key, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)&#91;0&#93;
        text_x = x + (key_size&#91;0&#93; - text_size&#91;0&#93;) // 2
        text_y = y + (key_size&#91;1&#93; + text_size&#91;1&#93;) // 2
        cv2.putText(
            frame,
            key,
            (text_x, text_y),
            cv2.FONT_HERSHEY_SIMPLEX,
            0.5,
            (0, 0, 0),
            1,
        )</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.draw_mouse_on_frame"><code>fastvideo.models.dits.matrixgame2.utils.draw_mouse_on_frame</code></h2>
<pre class="doc-signature"><code>draw_mouse_on_frame(frame: np.ndarray, yaw: float, pitch: float, top_margin: int = 15) -&gt; None</code></pre>

<details><summary>Source</summary><pre><code>def draw_mouse_on_frame(
    frame: np.ndarray,
    yaw: float,
    pitch: float,
    top_margin: int = 15,
) -&gt; None:
    if not _require_cv2():
        return

    _, width, _ = frame.shape
    right_margin = 15
    crosshair_radius = 25
    crosshair_x = width - right_margin - crosshair_radius
    crosshair_y = top_margin + crosshair_radius

    dx = int(yaw * crosshair_radius * 8)
    dy = int(-pitch * crosshair_radius * 8)
    max_arrow = crosshair_radius - 5
    dx = max(-max_arrow, min(max_arrow, dx))
    dy = max(-max_arrow, min(max_arrow, dy))

    cv2.circle(frame, (crosshair_x, crosshair_y), crosshair_radius, (50, 50, 50), -1)
    cv2.circle(frame, (crosshair_x, crosshair_y), crosshair_radius, (200, 200, 200), 1)
    cv2.line(
        frame,
        (crosshair_x - crosshair_radius + 5, crosshair_y),
        (crosshair_x + crosshair_radius - 5, crosshair_y),
        (100, 100, 100),
        1,
    )
    cv2.line(
        frame,
        (crosshair_x, crosshair_y - crosshair_radius + 5),
        (crosshair_x, crosshair_y + crosshair_radius - 5),
        (100, 100, 100),
        1,
    )

    if abs(dx) &gt; 1 or abs(dy) &gt; 1:
        cv2.arrowedLine(
            frame,
            (crosshair_x, crosshair_y),
            (crosshair_x + dx, crosshair_y + dy),
            (0, 255, 0),
            2,
            tipLength=0.3,
        )</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.overlay_validation_actions_on_frames"><code>fastvideo.models.dits.matrixgame2.utils.overlay_validation_actions_on_frames</code></h2>
<pre class="doc-signature"><code>overlay_validation_actions_on_frames(frames: list&#91;np.ndarray&#93;, keyboard_cond: np.ndarray | torch.Tensor | None = None, mouse_cond: np.ndarray | torch.Tensor | None = None) -&gt; list&#91;np.ndarray&#93;</code></pre>

<details><summary>Source</summary><pre><code>def overlay_validation_actions_on_frames(
    frames: list&#91;np.ndarray&#93;,
    keyboard_cond: np.ndarray | torch.Tensor | None = None,
    mouse_cond: np.ndarray | torch.Tensor | None = None,
) -&gt; list&#91;np.ndarray&#93;:
    if (keyboard_cond is None and mouse_cond is None) or not _require_cv2():
        return frames

    if keyboard_cond is not None and torch.is_tensor(keyboard_cond):
        keyboard_cond = keyboard_cond.detach().cpu().float().numpy()
    if mouse_cond is not None and torch.is_tensor(mouse_cond):
        mouse_cond = mouse_cond.detach().cpu().float().numpy()

    if keyboard_cond is not None:
        keyboard_cond = np.asarray(keyboard_cond, dtype=np.float32)
        if keyboard_cond.ndim == 3 and keyboard_cond.shape&#91;0&#93; == 1:
            keyboard_cond = keyboard_cond&#91;0&#93;
    if mouse_cond is not None:
        mouse_cond = np.asarray(mouse_cond, dtype=np.float32)
        if mouse_cond.ndim == 3 and mouse_cond.shape&#91;0&#93; == 1:
            mouse_cond = mouse_cond&#91;0&#93;

    processed_frames: list&#91;np.ndarray&#93; = &#91;&#93;
    for frame_idx, frame in enumerate(frames):
        frame = np.ascontiguousarray(frame.copy())
        if keyboard_cond is not None and frame_idx &lt; len(keyboard_cond):
            draw_keys_on_frame(
                frame,
                _matrixgame2_overlay_keys_from_keyboard(keyboard_cond&#91;frame_idx&#93;),
            )
        if mouse_cond is not None and frame_idx &lt; len(mouse_cond):
            # MG action convention: mouse&#91;0&#93;=pitch, mouse&#91;1&#93;=yaw.
            pitch = float(mouse_cond&#91;frame_idx, 0&#93;)
            yaw = float(mouse_cond&#91;frame_idx, 1&#93;)
            draw_mouse_on_frame(frame, yaw=yaw, pitch=pitch)
        processed_frames.append(frame)

    return processed_frames</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.scale_keyboard_condition"><code>fastvideo.models.dits.matrixgame2.utils.scale_keyboard_condition</code></h2>
<pre class="doc-signature"><code>scale_keyboard_condition(keyboard_condition: torch.Tensor, scale: float) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def scale_keyboard_condition(
    keyboard_condition: torch.Tensor,
    scale: float,
) -&gt; torch.Tensor:
    if float(scale) == 1.0:
        return keyboard_condition
    return keyboard_condition * float(scale)</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.expand_action_to_frames"><code>fastvideo.models.dits.matrixgame2.utils.expand_action_to_frames</code></h2>
<pre class="doc-signature"><code>expand_action_to_frames(action: dict, num_frames: int) -&gt; tuple&#91;torch.Tensor, torch.Tensor&#93;</code></pre>

<details><summary>Source</summary><pre><code>def expand_action_to_frames(action: dict, num_frames: int) -&gt; tuple&#91;torch.Tensor, torch.Tensor&#93;:
    result = &#123;&#125;
    for key, tensor in action.items():
        if tensor is not None:
            # Expand to &#91;num_frames, D&#93; then unsqueeze to &#91;1, num_frames, D&#93;
            result&#91;key&#93; = tensor.unsqueeze(0).repeat(num_frames, 1).unsqueeze(0)
        else:
            result&#91;key&#93; = None

    if &quot;mouse&quot; not in result or result&#91;&quot;mouse&quot;&#93; is None:
        # keyboard device if available, otherwise default
        device = result.get(&quot;keyboard&quot;, torch.tensor(
            &#91;&#93;)).device if result.get(&quot;keyboard&quot;) is not None else get_local_torch_device()
        result&#91;&quot;mouse&quot;&#93; = torch.zeros(1, num_frames, 2, device=device)

    return result&#91;&quot;keyboard&quot;&#93;, result&#91;&quot;mouse&quot;&#93;</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.get_current_action"><code>fastvideo.models.dits.matrixgame2.utils.get_current_action</code></h2>
<pre class="doc-signature"><code>get_current_action(mode = &#x27;universal&#x27;)</code></pre>

<details><summary>Source</summary><pre><code>def get_current_action(mode=&quot;universal&quot;):

    CAM_VALUE = 0.1
    if mode == &#x27;universal&#x27;:
        logger.info(&quot;&quot;)
        logger.info(&#x27;-&#x27; * 30)
        logger.info(&quot;PRESS &#91;I, K, J, L, U&#93; FOR CAMERA TRANSFORM\n (I: up, K: down, J: left, L: right, U: no move)&quot;)
        logger.info(&quot;PRESS &#91;W, S, A, D, Q&#93; FOR MOVEMENT\n (W: forward, S: back, A: left, D: right, Q: no move)&quot;)
        logger.info(&#x27;-&#x27; * 30)
        CAMERA_VALUE_MAP = &#123;
            &quot;i&quot;: &#91;CAM_VALUE, 0&#93;,
            &quot;k&quot;: &#91;-CAM_VALUE, 0&#93;,
            &quot;j&quot;: &#91;0, -CAM_VALUE&#93;,
            &quot;l&quot;: &#91;0, CAM_VALUE&#93;,
            &quot;u&quot;: &#91;0, 0&#93;
        &#125;
        KEYBOARD_IDX = &#123;&quot;w&quot;: &#91;1, 0, 0, 0&#93;, &quot;s&quot;: &#91;0, 1, 0, 0&#93;, &quot;a&quot;: &#91;0, 0, 1, 0&#93;, &quot;d&quot;: &#91;0, 0, 0, 1&#93;, &quot;q&quot;: &#91;0, 0, 0, 0&#93;&#125;
        flag = 0
        while flag != 1:
            try:
                idx_mouse = input(&#x27;Please input the mouse action (e.g. `U`):\n&#x27;).strip().lower()
                idx_keyboard = input(&#x27;Please input the keyboard action (e.g. `W`):\n&#x27;).strip().lower()
                if idx_mouse in CAMERA_VALUE_MAP and idx_keyboard in KEYBOARD_IDX:
                    flag = 1
            except Exception:
                pass
        mouse_cond = torch.tensor(CAMERA_VALUE_MAP&#91;idx_mouse&#93;).cuda()
        keyboard_cond = torch.tensor(KEYBOARD_IDX&#91;idx_keyboard&#93;).cuda()
    elif mode == &#x27;gta_drive&#x27;:
        logger.info(&quot;&quot;)
        logger.info(&#x27;-&#x27; * 30)
        logger.info(&quot;PRESS &#91;W, S, A, D, Q&#93; FOR MOVEMENT\n (W: forward, S: back, A: left, D: right, Q: no move)&quot;)
        logger.info(&#x27;-&#x27; * 30)
        CAMERA_VALUE_MAP = &#123;&quot;a&quot;: &#91;0, -CAM_VALUE&#93;, &quot;d&quot;: &#91;0, CAM_VALUE&#93;, &quot;q&quot;: &#91;0, 0&#93;&#125;
        KEYBOARD_IDX = &#123;&quot;w&quot;: &#91;1, 0&#93;, &quot;s&quot;: &#91;0, 1&#93;, &quot;q&quot;: &#91;0, 0&#93;&#125;
        flag = 0
        while flag != 1:
            try:
                indexes = input(
                    &#x27;Please input the actions (split with ` `):\n(e.g. `W` for forward, `W A` for forward and left)\n&#x27;
                ).strip().lower().split(&#x27; &#x27;)
                idx_mouse = &#91;&#93;
                idx_keyboard = &#91;&#93;
                for i in indexes:
                    if i in CAMERA_VALUE_MAP.keys():
                        idx_mouse += &#91;i&#93;
                    elif i in KEYBOARD_IDX.keys():
                        idx_keyboard += &#91;i&#93;
                if len(idx_mouse) == 0:
                    idx_mouse += &#91;&#x27;q&#x27;&#93;
                if len(idx_keyboard) == 0:
                    idx_keyboard += &#91;&#x27;q&#x27;&#93;
                assert idx_mouse in &#91;&#91;&#x27;a&#x27;&#93;, &#91;&#x27;d&#x27;&#93;, &#91;&#x27;q&#x27;&#93;&#93; and idx_keyboard in &#91;&#91;&#x27;q&#x27;&#93;, &#91;&#x27;w&#x27;&#93;, &#91;&#x27;s&#x27;&#93;&#93;
                flag = 1
            except Exception:
                pass
        mouse_cond = torch.tensor(CAMERA_VALUE_MAP&#91;idx_mouse&#91;0&#93;&#93;).cuda()
        keyboard_cond = torch.tensor(KEYBOARD_IDX&#91;idx_keyboard&#91;0&#93;&#93;).cuda()
    elif mode == &#x27;templerun&#x27;:
        logger.info(&quot;&quot;)
        logger.info(&#x27;-&#x27; * 30)
        logger.info(
            &quot;PRESS &#91;W, S, A, D, Z, C, Q&#93; FOR ACTIONS\n (W: jump, S: slide, A: left side, D: right side, Z: turn left, C: turn right, Q: no move)&quot;
        )
        logger.info(&#x27;-&#x27; * 30)
        KEYBOARD_IDX = &#123;
            &quot;w&quot;: &#91;0, 1, 0, 0, 0, 0, 0&#93;,
            &quot;s&quot;: &#91;0, 0, 1, 0, 0, 0, 0&#93;,
            &quot;a&quot;: &#91;0, 0, 0, 0, 0, 1, 0&#93;,
            &quot;d&quot;: &#91;0, 0, 0, 0, 0, 0, 1&#93;,
            &quot;z&quot;: &#91;0, 0, 0, 1, 0, 0, 0&#93;,
            &quot;c&quot;: &#91;0, 0, 0, 0, 1, 0, 0&#93;,
            &quot;q&quot;: &#91;1, 0, 0, 0, 0, 0, 0&#93;
        &#125;
        flag = 0
        while flag != 1:
            try:
                idx_keyboard = input(
                    &#x27;Please input the action: \n(e.g. `W` for forward, `Z` for turning left)\n&#x27;).strip().lower()
                if idx_keyboard in KEYBOARD_IDX.keys():
                    flag = 1
            except Exception:
                pass
        keyboard_cond = torch.tensor(KEYBOARD_IDX&#91;idx_keyboard&#93;).cuda()

    if mode != &#x27;templerun&#x27;:
        return &#123;&quot;mouse&quot;: mouse_cond, &quot;keyboard&quot;: keyboard_cond&#125;
    return &#123;&quot;keyboard&quot;: keyboard_cond&#125;</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.get_current_action_async"><code>fastvideo.models.dits.matrixgame2.utils.get_current_action_async</code></h2>
<pre class="doc-signature"><code>get_current_action_async(mode = &#x27;universal&#x27;)</code></pre>

<details><summary>Source</summary><pre><code>async def get_current_action_async(mode=&quot;universal&quot;):
    return await asyncio.to_thread(get_current_action, mode)</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.load_initial_image"><code>fastvideo.models.dits.matrixgame2.utils.load_initial_image</code></h2>
<pre class="doc-signature"><code>load_initial_image(image_path: str = None) -&gt; Image.Image</code></pre>

<details><summary>Source</summary><pre><code>def load_initial_image(image_path: str = None) -&gt; Image.Image:
    if image_path and os.path.exists(image_path):
        return Image.open(image_path).convert(&quot;RGB&quot;)
    logger.warning(&quot;No image provided, creating placeholder...&quot;)
    return Image.new(&quot;RGB&quot;, (640, 352), (128, 128, 128))</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.create_action_presets"><code>fastvideo.models.dits.matrixgame2.utils.create_action_presets</code></h2>
<pre class="doc-signature"><code>create_action_presets(num_frames: int, keyboard_dim: int = 4, seed: int = None)</code></pre>

<details><summary>Source</summary><pre><code>def create_action_presets(num_frames: int, keyboard_dim: int = 4, seed: int = None):
    if keyboard_dim not in (2, 4, 6, 7):
        raise ValueError(f&quot;keyboard_dim must be 2, 4, 6, or 7, got &#123;keyboard_dim&#125;&quot;)
    if num_frames % 4 != 1:
        raise ValueError(&quot;Matrix-Game conditioning expects num_frames to be 4k+1.&quot;)

    # Set seed for reproducibility if provided
    if seed is not None:
        random.seed(seed)

    num_samples_per_action = 4

    # Define actions based on keyboard_dim
    if keyboard_dim == 4:
        # Universal model: W, S, A, D
        actions_single_action = &#91;&quot;forward&quot;, &quot;left&quot;, &quot;right&quot;&#93;
        actions_double_action = &#91;&quot;forward_left&quot;, &quot;forward_right&quot;&#93;
        actions_single_camera = &#91;&quot;camera_l&quot;, &quot;camera_r&quot;&#93;
        keyboard_idx = &#123;&quot;forward&quot;: 0, &quot;back&quot;: 1, &quot;left&quot;: 2, &quot;right&quot;: 3&#125;
    elif keyboard_dim == 2:
        # GTA model: W, S only (steering via mouse)
        actions_single_action = &#91;&quot;forward&quot;, &quot;back&quot;&#93;
        actions_double_action = &#91;&#93;
        actions_single_camera = &#91;&quot;camera_l&quot;, &quot;camera_r&quot;&#93;
        keyboard_idx = &#123;&quot;forward&quot;: 0, &quot;back&quot;: 1&#125;
    elif keyboard_dim == 6:
        actions_single_action = &#91;&quot;forward&quot;, &quot;back&quot;, &quot;left&quot;, &quot;right&quot;&#93;
        actions_double_action = &#91;&quot;forward_left&quot;, &quot;forward_right&quot;&#93;
        actions_single_camera = &#91;&quot;camera_l&quot;, &quot;camera_r&quot;&#93;
        keyboard_idx = &#123;&quot;forward&quot;: 0, &quot;back&quot;: 1, &quot;left&quot;: 2, &quot;right&quot;: 3, &quot;t1&quot;: 4, &quot;t2&quot;: 5&#125;
    else:  # keyboard_dim == 7
        # Temple Run model: still, w, s, left, right, a, d (no mouse)
        actions_single_action = &#91;&quot;forward&quot;, &quot;back&quot;, &quot;left&quot;, &quot;right&quot;&#93;
        actions_double_action = &#91;&#93;
        actions_single_camera = &#91;&#93;  # No mouse for Temple Run
        keyboard_idx = &#123;&quot;still&quot;: 0, &quot;forward&quot;: 1, &quot;back&quot;: 2, &quot;left&quot;: 3, &quot;right&quot;: 4, &quot;a&quot;: 5, &quot;d&quot;: 6&#125;

    actions_to_test = (actions_double_action * 5 + actions_single_camera * 5 + actions_single_action * 5)
    for action in (actions_single_action + actions_double_action):
        for camera in actions_single_camera:
            actions_to_test.append(f&quot;&#123;action&#125;_&#123;camera&#125;&quot;)

    # Ensure we have at least some actions
    if not actions_to_test:
        actions_to_test = actions_single_action * 5

    base_action = actions_single_action + actions_single_camera
    cam_value = 0.1
    camera_value_map = &#123;
        &quot;camera_up&quot;: &#91;cam_value, 0&#93;,
        &quot;camera_down&quot;: &#91;-cam_value, 0&#93;,
        &quot;camera_l&quot;: &#91;0, -cam_value&#93;,
        &quot;camera_r&quot;: &#91;0, cam_value&#93;,
        &quot;camera_ur&quot;: &#91;cam_value, cam_value&#93;,
        &quot;camera_ul&quot;: &#91;cam_value, -cam_value&#93;,
        &quot;camera_dr&quot;: &#91;-cam_value, cam_value&#93;,
        &quot;camera_dl&quot;: &#91;-cam_value, -cam_value&#93;,
    &#125;

    data = &#91;&#93;
    for action_name in actions_to_test:
        keyboard_condition = torch.zeros((num_samples_per_action, keyboard_dim))
        mouse_condition = torch.zeros((num_samples_per_action, 2))

        for sub_act in base_action:
            if sub_act not in action_name:
                continue
            if sub_act in camera_value_map:
                mouse_condition = torch.tensor(
                    &#91;camera_value_map&#91;sub_act&#93; for _ in range(num_samples_per_action)&#93;,
                    dtype=mouse_condition.dtype,
                )
            elif sub_act in keyboard_idx:
                keyboard_condition&#91;:, keyboard_idx&#91;sub_act&#93;&#93; = 1

        data.append(&#123;
            &quot;keyboard_condition&quot;: keyboard_condition,
            &quot;mouse_condition&quot;: mouse_condition,
        &#125;)

    keyboard_condition = torch.zeros((num_frames, keyboard_dim))
    mouse_condition = torch.zeros((num_frames, 2))
    current_frame = 0
    selections = &#91;12&#93;

    while current_frame &lt; num_frames:
        rd_frame = selections&#91;random.randint(0, len(selections) - 1)&#93;
        entry = data&#91;random.randint(0, len(data) - 1)&#93;
        key_seq = entry&#91;&quot;keyboard_condition&quot;&#93;
        mouse_seq = entry&#91;&quot;mouse_condition&quot;&#93;

        if current_frame == 0:
            keyboard_condition&#91;:1&#93; = key_seq&#91;:1&#93;
            mouse_condition&#91;:1&#93; = mouse_seq&#91;:1&#93;
            current_frame = 1
        else:
            rd_frame = min(rd_frame, num_frames - current_frame)
            repeat_time = rd_frame // 4
            keyboard_condition&#91;current_frame:current_frame + rd_frame&#93; = key_seq.repeat(repeat_time, 1)
            mouse_condition&#91;current_frame:current_frame + rd_frame&#93; = mouse_seq.repeat(repeat_time, 1)
            current_frame += rd_frame

    return &#123;&quot;keyboard&quot;: keyboard_condition, &quot;mouse&quot;: mouse_condition&#125;</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame2.utils.parse_config"><code>fastvideo.models.dits.matrixgame2.utils.parse_config</code></h2>
<pre class="doc-signature"><code>parse_config(config, mode = &#x27;universal&#x27;)</code></pre>

<details><summary>Source</summary><pre><code>def parse_config(config, mode=&quot;universal&quot;):
    assert mode in &#91;&#x27;universal&#x27;, &#x27;gta_drive&#x27;, &#x27;templerun&#x27;&#93;
    key_data = &#123;&#125;
    mouse_data = &#123;&#125;
    if mode != &#x27;templerun&#x27;:
        key, mouse = config
    else:
        key = config

    for i in range(len(key)):
        if mode == &#x27;templerun&#x27;:
            still, w, s, left, right, a, d = key&#91;i&#93;
        elif mode == &#x27;universal&#x27;:
            w, s, a, d = key&#91;i&#93;
        else:
            w, s, a, d = key&#91;i&#93;&#91;0&#93;, key&#91;i&#93;&#91;1&#93;, mouse&#91;i&#93;&#91;1&#93; &lt; 0, mouse&#91;i&#93;&#91;1&#93; &gt; 0
        if mode == &#x27;universal&#x27;:
            mouse_y, mouse_x = mouse&#91;i&#93;
            mouse_y = -1 * mouse_y

        key_data&#91;i&#93; = &#123;&quot;W&quot;: bool(w), &quot;A&quot;: bool(a), &quot;S&quot;: bool(s), &quot;D&quot;: bool(d)&#125;
        if mode == &#x27;templerun&#x27;:
            key_data&#91;i&#93;.update(&#123;&quot;left&quot;: bool(left), &quot;right&quot;: bool(right)&#125;)

        if mode == &#x27;universal&#x27;:
            if i == 0:
                mouse_data&#91;i&#93; = (320, 352 // 2)
            else:
                global_scale_factor = 0.1
                mouse_scale_x = 15 * global_scale_factor
                mouse_scale_y = 15 * 4 * global_scale_factor
                mouse_data&#91;i&#93; = (
                    mouse_data&#91;i - 1&#93;&#91;0&#93; + mouse_x * mouse_scale_x,
                    mouse_data&#91;i - 1&#93;&#91;1&#93; + mouse_y * mouse_scale_y,
                )
    return key_data, mouse_data</code></pre></details>
</div>
