o
    }oiD                  #   @   s  d dl Z d dlmZmZmZmZmZmZ d dlZ	d dl
Z
d dlm  mZ d dlmZ d dlmZ d dlmZmZmZmZ dededed	efd
dZddgd dgd dgdddddddddfdedee dee dee dededededed ed!ed"ed#e
jd	ee
je
je
je
jee
j f fd$d%Zded&e
jd#e
jd	ee
je
je
jf fd'd(Z	d-ded&e
jde	j de	j d#e
jd	ee
je
je
jf fd)d*Z!G d+d, d,eZ"dS ).    N)AnyDictIteratorListOptionalTuple)IterableDataset)PinholeCamera)compute_look_at_vectorsconstruct_posesget_raysget_view_directionxlower_boundupper_boundreturnc                 C   s   t dtd| | ||  S )aD  
    Linearly normalize a value between lower_bound and upper_bound to a value between 0 and 1.

    Parameters:
        x: The value to normalize.
        lower_bound: The lower bound of the range of x.
        upper_bound: The upper bound of the range of x.

    Returns:
        The normalized value between 0 and 1.
       r   )minmaxr   r   r    r   f/home/ubuntu/.local/lib/python3.10/site-packages/nemo/collections/multimodal/data/nerf/random_poses.pylinear_normalization    s   r   r   g      ?x   h     <   g      ?F皙?{Gz?cudasizeradius_rangetheta_range	phi_rangeangle_overheadangle_frontuniform_sphere_ratejitterjitter_centerjitter_target	jitter_upreturn_dirsdevicec                 C   s*  t |}t |}t |}t |}tj| |d|d |d   |d  }t |k r8t| ||d\}}}nt| ||||d\}}}t|}|r_|t|| |d  7 }t	||	 }t
|| |rg|
nd|d\}}}t|||||d}|rt||||nd	}t|t|}}|||||fS )
aa  
    Generate random poses from an orbit camera.

    Args:
        size (int): Number of poses to generate.
        radius_range (List[float]): Min and max radii for camera [min, max].
        theta_range (List[float]): Elevation angle range in degrees [min, max].
        phi_range (List[float]): Azimuth angle range in degrees [min, max].
        angle_overhead (float): Overhead angle in degrees.
        angle_front (float): Front angle in degrees.
        uniform_sphere_rate (float): The probability of sampling from a uniform sphere.
        jitter (bool): Whether to add noise to the poses.
        jitter_center (float): Noise range for the camera center.
        jitter_target (float): Noise range for the camera target.
        jitter_up (float): Noise range for the camera up vector.
        return_dirs (bool): Whether to return the view directions.
        device (torch.device): The device on which to allocate tensors.

    Returns:
        Tuple: Contains the following:
            - poses (torch.Tensor): Generated poses, shape [size, 4, 4].
            - thetas (torch.Tensor): Elevation angles in degrees, shape [size].
            - phis (torch.Tensor): Azimuth angles in degrees, shape [size].
            - radius (torch.Tensor): Radii of the camera orbits, shape [size].
            - dirs (torch.Tensor, optional): View directions, if requested.
    r,   r   r   )r    radiusr,   )r    r.   r"   r#   r,   g       @)centersr*   r,   )r/   right_vector	up_vectorforward_vectorr,   N)npradianstorchrandrandomsample_uniform_spheresample_orbit
zeros_like	rand_like
randn_liker
   r   r   rad2deg)r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r.   r/   thetasphistargetsr2   r1   r0   posesdirsr   r   r   
rand_poses/   s.   
+


&


rC   r.   c              	   C   s   t jtjtj| |dttj| |dtj| |dgddddd}||d }t|dddf }t|dddf |dddf }||dk   dt	j
 7  < |||fS )	a  
    Sample points uniformly on a sphere.

    Args:
        size (int): Number of points to sample.
        device (torch.device): Device to allocate tensors on.
        radius (torch.Tensor): Radii for the points.

    Returns:
        Tuple: Contains the following:
            - centers (torch.Tensor): The Cartesian coordinates of the sampled points.
            - thetas (torch.Tensor): Elevation angles in radians.
            - phis (torch.Tensor): Azimuth angles in radians.
    r-   dim   r   )prF   Nr   )F	normalizer5   stackrandnabs	unsqueezeacosatan2r3   pi)r    r.   r,   unit_centersr/   r>   r?   r   r   r   r8      s    $
r8   c                 C   s   t j| |d|d |d   |d  }t j| |d|d |d   |d  }||dk   dtj 7  < |t | t | }|t | }|t | t | }	t j|||	gdd}
|
||fS )a  
    Sample points on a spherical orbit.

    Args:
        size (int): Number of points to sample.
        radius (torch.Tensor): Radii for the points.
        theta_range (np.ndarray): Elevation angle range in radians [min, max].
        phi_range (np.ndarray): Azimuth angle range in radians [min, max].
        device (torch.device): Device to allocate tensors on.

    Returns:
        Tuple: Contains the following:
            - centers (torch.Tensor): The Cartesian coordinates of the sampled points.
            - thetas (torch.Tensor): Elevation angles in radians.
            - phis (torch.Tensor): Azimuth angles in radians.
    r-   r   r   rG   rD   rE   )r5   r6   r3   rQ   sincosrK   )r    r.   r"   r#   r,   r>   r?   r   yzr/   r   r   r   r9      s   &&
r9   c                1       sb  e Zd ZdZdddddgddgdd	gd
dgdd
dgddddddddddddddfdedededeeef deeef deeef deeef dedeeef d ed!ed"ed#ed$ed%ed&ed'ed(ed)ed*ed+ed,ed-ej	d.d/f0 fd0d1Z
d2ed3ed.d/fd4d5Zd3ed.d/fd6d7Zd.eeeejf  fd8d9Zd:d; Zd<eeeef  d.eeef fd=d>Z  ZS )?RandomPosesDatasetz3
    A dataset class to generate random poses.
    d      g      @g      @g     F@g     @Z@g     fg     f@g      $@g      >@g      4@g	@g     V@g        Fr   r   g      N@g{Gz?g     @@cpuinternal_batch_sizeheightwidthr!   r"   r#   
fovx_rangedefault_fovx
fovy_rangedefault_fovydefault_radiusdefault_polardefault_azimuthr'   r(   r)   r*   r$   r%   r&   nearfarr,   r   Nc                    s   t    || _|| _|| _d| _d| _d| _|| _|
| _	|| _
|| _|| _d| _|| _|| _|| _|| _|	| _|| _|| _|| _|| _|	| _|| _|| _|| _|| _|| _|| _|| _|| _|| _ || _!t"| j| j| j| j | j!d| _#dS )a.  
        Initializes a new RandomPosesDataset instance.

        Parameters:
            internal_batch_size (int): Number of samples to pre-generate internally.
            height (int): Height of the image.
            width (int): Width of the image.
            radius_range (Tuple[float, float]): Range of generated radii.
            theta_range (Tuple[float, float]): Range of generated theta angles.
            phi_range (Tuple[float, float]): Range of generated phi angles.
            fovx_range (Tuple[float, float]): Range of generated field of view in x-direction.
            default_fovx (float): Default field of view in x-direction.
            fovy_range (Tuple[float, float]): Range of generated field of view angles in y-direction.
            default_fovy (float): Default field of view in y-direction.
            default_radius (float): Default radius of the circle.
            default_polar (float): Default polar angle.
            default_azimuth (float): Default azimuth angle.
            jitter (bool): Whether to jitter the poses.
            jitter_center (float): Jittering center range.
            jitter_target (float): Jittering target range.
            jitter_up (float): Jittering up range.
            angle_overhead (float): Overhead angle.
            angle_front (float): Frontal angle.
            uniform_sphere_rate (float): Rate of sampling uniformly on a sphere.
            near (float): Near clipping distance.
            far (float): Far clipping distance.
            device (torch.device): Device to generate data on.
        Fr   i  T)r]   r\   re   rf   r,   N)$super__init__r\   r]   r[   progressive_viewprogressive_view_start_stepprogressive_view_end_stepr_   ra   rb   rc   rd   same_fov_randomr!   r"   r#   r^   r`   current_radius_rangecurrent_theta_rangecurrent_phi_rangecurrent_fovx_rangecurrent_fovy_ranger$   r%   r&   r'   r(   r)   r*   re   rf   r,   r	   camera)selfr[   r\   r]   r!   r"   r#   r^   r_   r`   ra   rb   rc   rd   r'   r(   r)   r*   r$   r%   r&   re   rf   r,   	__class__r   r   rh      sH   
7zRandomPosesDataset.__init__epochglobal_stepc                 C   s   | j r| j|d dS dS )z
        Update the dataset at the beginning of each epoch.

        Parameters:
            epoch (int): Current epoch.
            global_step (int): Current global step.

        )rw   N)ri   progressive_view_update_step)rs   rv   rw   r   r   r   update_step8  s   	zRandomPosesDataset.update_stepc                 C   s   t || j| jd}d| | j || jd   d| | j || jd   g| _d| | j || jd   d| | j || jd   g| _d| | j	 || j
d   d| | j	 || j
d   g| _d| | j || jd   d| | j || jd   g| _dS )z|
        progressively relaxing view range

        Parameters:
            global_step (int): Current global step.
        r   r   r   N)r   rj   rk   rd   r#   ro   rc   r"   rn   rb   r!   rm   ra   r`   rq   )rs   rw   rr   r   r   rx   D  s   

z/RandomPosesDataset.progressive_view_update_stepc              
   c   st    	 |   \}}}}}t| jD ](}| j| j|| d|| d|| d|| d|| ddV  qq)z~
        Returns an iterator over the dataset.

        Returns:
            Iterator: An iterator over the dataset.

        Tr   )r\   r]   rays_orays_ddirmvpazimuth)generate_samplesranger[   r\   r]   rN   )rs   r{   r|   rB   r~   delta_azimuthir   r   r   __iter__`  s   
zRandomPosesDataset.__iter__c                 C   s*  t | j| j| j| j| j| j| j| j| j	| j
| jd| jd\}}}}}| jr,t }|}nt }t }|| jd | jd   | jd  }|| jd | jd   | jd  }	| jj||	d}
| jj|
d |
d d}|t| }t||
| j| j|jd\}}|| j }||dk  d	8  < |||||fS )
a  
        Generate a batch of random poses.

        Returns:
            Tuple[Dict[str, torch.Tensor], Dict[str, torch.Tensor], Dict[str, torch.Tensor], Dict[str, torch.Tensor], Dict[str, torch.Tensor]]:
                A tuple containing:
                    - rays (Dict[str, torch.Tensor]): A dictionary containing the origin and direction of the rays.
                    - dirs (torch.Tensor): A tensor containing the directions of the rays.
                    - mvp (torch.Tensor): A tensor containing the model-view-projection matrix.
                    - azimuth (torch.Tensor): A A tensor containing the azimuth angle.
        T)r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r   r   )fovxfovy)focal_xfocal_y)rA   
intrinsicsr\   r]   r,      r   )rC   r[   rm   rn   ro   r$   r%   r&   r'   r(   r)   r*   r,   rl   r7   rp   rq   rr   compute_intrinsicscompute_projection_matrixr5   inverser   r\   r]   rd   )rs   rA   rB   r>   r?   r.   fovx_randomfovy_randomr   r   r   
projectionr~   r{   r|   r   r   r   r   r   w  s>   ""

z#RandomPosesDataset.generate_samplesbatchc              
   C   s|   | j | jtjdd |D ddtjdd |D ddtjdd |D ddtjdd |D ddtjdd |D ddd	S )
z
        Collate function to bundle multiple samples into a single batch.

        Args:
            batch (List[Dict]): List of samples to collate.

        Returns:
            Dict: A dictionary containing the collated batch.
        c                 S      g | ]}|d  qS )r{   r   .0itemr   r   r   
<listcomp>      z1RandomPosesDataset.collate_fn.<locals>.<listcomp>r   rE   c                 S   r   )r|   r   r   r   r   r   r     r   c                 S   r   )r~   r   r   r   r   r   r     r   c                 S   r   )r}   r   r   r   r   r   r     r   c                 S   r   )r   r   r   r   r   r   r     r   )r\   r]   r{   r|   r~   r}   r   )r\   r]   r5   cat)rs   r   r   r   r   
collate_fn  s   zRandomPosesDataset.collate_fn)__name__
__module____qualname____doc__intr   floatboolr5   r,   rh   ry   rx   r   r   strTensorr   r   r   r   r   __classcell__r   r   rt   r   rW      s    



	

f.9rW   )r   )#r7   typingr   r   r   r   r   r   numpyr3   r5   torch.nn.functionalnn
functionalrI   torch.utils.datar   -nemo.collections.multimodal.data.nerf.camerasr	   +nemo.collections.multimodal.data.nerf.utilsr
   r   r   r   r   r   r   r   r,   r   rC   r8   ndarrayr9   rW   r   r   r   r   <module>   s    	

V
)
 