//  [python]
def get_render_rays(self, img_idx: int) -> Dict[str, Tensor]:
        """
        Get the rays for rendering the given image index.
        Args:
            img_idx: the image index.
        Returns:
            a dict containing the rays for rendering the given image index.
        """
        rgb, sky_mask, dynamic_mask, features = None, None, None, None
        pixel_coords, normalized_timestamps = None, None
        if self.images is not None:
            rgb = self.images[img_idx]
            if self.downscale_factor != 1.0:
                rgb = (
                    torch.nn.functional.interpolate(
                        rgb.unsqueeze(0).permute(0, 3, 1, 2),
                        scale_factor=self.downscale_factor,
                        mode="bicubic",
                        antialias=True,
                    )
                    .squeeze(0)
                    .permute(1, 2, 0)
                )
                img_height, img_width = rgb.shape[:2]
            else:
                img_height, img_width = self.HEIGHT, self.WIDTH

        x, y = torch.meshgrid(
            torch.arange(img_width),
            torch.arange(img_height),
            indexing="xy",
        )
        x, y = x.flatten(), y.flatten()
        x, y = x.to(self.device), y.to(self.device)
        # pixel coordinates
        pixel_coords = (
            torch.stack([y / img_height, x / img_width], dim=-1)
            .float()
            .reshape(img_height, img_width, 2)
        )

        if self.sky_masks is not None:
            sky_mask = self.sky_masks[img_idx]
            if self.downscale_factor != 1.0:
                sky_mask = (
                    torch.nn.functional.interpolate(
                        sky_mask.unsqueeze(0).unsqueeze(0),
                        scale_factor=self.downscale_factor,
                        mode="nearest",
                    )
                    .squeeze(0)
                    .squeeze(0)
                )
        if self.dynamic_masks is not None:
            dynamic_mask = self.dynamic_masks[img_idx].float()
            if self.downscale_factor != 1.0:
                dynamic_mask = (
                    torch.nn.functional.interpolate(
                        dynamic_mask.unsqueeze(0).unsqueeze(0),
                        scale_factor=self.downscale_factor,
                        mode="nearest",
                    )
                    .squeeze(0)
                    .squeeze(0)
                )
        if self.features is not None:
            features = self.get_features(
                img_idx,
                y,
                x,
                downscale=(
                    self.featmap_downscale_factor[0] / self.downscale_factor,
                    self.featmap_downscale_factor[1] / self.downscale_factor,
                ),
            ).reshape(img_height, img_width, -1)

        if self.normalized_timestamps is not None:
            normalized_timestamps = torch.full(
                (img_height, img_width),
                self.normalized_timestamps[img_idx],
                dtype=torch.float32,
            )
        if self.cam_ids is not None:
            camera_id = torch.full(
                (img_height, img_width),
                self.cam_ids[img_idx],
                dtype=torch.long,
            )
        image_id = torch.full(
            (img_height, img_width),
            img_idx,
            dtype=torch.long,
        )
        c2w = self.cam_to_worlds[img_idx]
        intrinsics = self.intrinsics[img_idx] * self.downscale_factor
        intrinsics[2, 2] = 1.0
        origins, viewdirs, direction_norm = get_rays(x, y, c2w, intrinsics)
        origins = origins.reshape(img_height, img_width, 3)
        viewdirs = viewdirs.reshape(img_height, img_width, 3)
        direction_norm = direction_norm.reshape(img_height, img_width, 1)
        data = {
            "origins": origins,
            "viewdirs": viewdirs,
            "direction_norm": direction_norm,
            "pixel_coords": pixel_coords,
            "normed_timestamps": normalized_timestamps,
            "img_idx": image_id,
            "cam_idx": camera_id,
            "pixels": rgb,
            "sky_masks": sky_mask,
            "dynamic_masks": dynamic_mask,
            "features": features,
        }
        return {k: v for k, v in data.items() if v is not None}