o
    M4h                     @   s   d dl Z d dlZd dlZd dlmZmZ d dlmZ d dlZ	d dl
Z
d dlmZ d dlZd dlmZ dddZdd
dZG dd deZG dd de	jZdS )    N)Dataset
DataLoader)
transforms)train_test_split)get_smaller_structures_mask#~/DP/data/syn_3d.py/extracted_data/c                 C   sz   g }g }t j| d}t j| d}tt j|dD ]}t j|}|t j|| |t j|| q||fS )z
    Load raw image and corresponding segmentation mask paths from the dataset directory.

    Args:
        root (str): Root directory containing 'raw' and 'seg' subdirectories.

    Returns:
        tuple: Two lists of paths - images and masks.
    rawsegz*.nii.gz)ospathjoinglobbasenameappend)rootimagesmasksZimages_pathZ
masks_pathfile
image_name r   -/home/xmoravc/AI_project/dataloader/syn_3d.pyload_datasets   s   
r   *   c           	      C   sJ   t | t| |d|d\}}}}t||d|d\}}}}||||||fS )a0  
    Split the dataset into train, validation, and test sets.

    Args:
        images (list): List of image file paths.
        masks (list): List of mask file paths.
        random_seed (int): Random seed for reproducibility.

    Returns:
        tuple: Lists of train/val/test images and masks.
    g?)Z	test_sizerandom_state)randomseedr   )	r   r   random_seedtrain_imagestest_imagestrain_masks
test_masks
val_images	val_masksr   r   r   make_splits%   s   
r#   c                   @   sF   e Zd ZdZ				dddZdd Zdd
dZdddZdd ZdS )Syn3Da  
    PyTorch Dataset for loading 3D synthetic medical image volumes with optional augmentation and noise.

    Args:
        root_dir (str): Path to dataset root.
        images (list): List of image file paths (.nii.gz).
        masks (list): List of corresponding mask file paths (.nii.gz).
        split (str): One of ['train', 'val', 'test'] to determine augmentation behavior.
        add_noise (float): Std of Gaussian noise to add. If < 0, a random std [0, 0.45] will be sampled each time.
    Ntrainr   c                 C   s,   || _ || _|| _|| _t | _|| _d S N)root_dirr   r   splitr   ToTensor	transform	add_noise)selfr'   r   r   r(   r+   r   r   r   __init__E   s   

zSyn3D.__init__c                 C   s
   t | jS r&   )lenr   r,   r   r   r   __len__R   s   
zSyn3D.__len__r   r   r   c           
      C   s   |j \}}}td||d  }td||d  }td||d  }	||||d  |||d  |	|	|d  f }||||d  |||d  |	|	|d  f }||fS )aA  
        Perform random cropping of 3D image and mask volumes.

        Args:
            image (ndarray): 3D image volume.
            mask (ndarray): 3D segmentation mask.
            crop_factor (tuple): Desired output dimensions (z, y, x).

        Returns:
            tuple: Cropped image and mask volumes.
        r         )shaper   randint)
r,   imagemaskcrop_factorwhdzyxr   r   r   random_cropU   s   22zSyn3D.random_cropc                 C   s6   |du r| j }t|| }|| }t|dd}|S )a  
        Add Gaussian noise to the 3D image tensor.

        Args:
            image (Tensor): Input image tensor of shape (1, D, H, W).
            std (float, optional): Standard deviation of the noise.

        Returns:
            Tensor: Noisy image tensor.
        Nr   r2   )r+   torch
randn_likeclamp)r,   r6   stdnoisenoisy_imager   r   r   add_gausian_noisej   s   zSyn3D.add_gausian_noisec                 C   s   t | j|  }t | j|  }| j||dd\}}t|dd}tj|d tj	d}tj|tj	d}|
d}|
d}tj|tj	d
d}| j}| jdk rYtdd}| j||d	}|||fS )
z
        Load and process a sample from the dataset.

        Returns:
            tuple: (noisy_image, ground_truth_mask, postprocessed_mask)
        )   rG   rG   )r8      )Zker_size   )dtyper   g?)rC   )nibloadr   Z	get_fdatar   r?   r   r@   tensorfloat32	unsqueezer+   r   uniformrF   )r,   idxr6   r7   Zopened_maskrC   rE   r   r   r   __getitem__|   s   



zSyn3D.__getitem__)NNr%   r   )r1   r&   )	__name__
__module____qualname____doc__r-   r0   r?   rF   rR   r   r   r   r   r$   :   s    


r$   c                       sD   e Zd ZdZd fdd	Zddd	Zd
d Zdd Zdd Z  Z	S )Syn3DLightningaN  
    PyTorch Lightning DataModule for handling the Syn3D dataset.

    Args:
        root_dir (str): Root path to the dataset.
        batch_size (int): Number of samples per batch.
        num_workers (int): Number of subprocesses used for data loading.
        add_noise (float): Standard deviation for Gaussian noise to apply.
    r2      r   c                    s<   t t|   || _|| _|| _|| _d | _d | _d | _	d S r&   )
superrW   r-   r'   
batch_sizenum_workersr+   train_datasetval_datasettest_dataset)r,   r'   rZ   r[   r+   	__class__r   r   r-      s   
zSyn3DLightning.__init__Nc           
      C   s   t | jd\}}t||\}}}}}}	|dks|du r3t| j||d| jd| _t| j||d| jd| _|dks;|du rIt| j||	d| jd| _dS dS )z
        Setup datasets for different stages: 'fit' (train/val) and 'test'.

        Args:
            stage (str, optional): Either 'fit', 'test', or None for both.
        )r   fitNr%   )r'   r   r   r(   r+   valtest)r   r'   r#   r$   r+   r\   r]   r^   )
r,   stager   r   r   r   r!   r"   r   r    r   r   r   setup   s   zSyn3DLightning.setupc                 C      t | j| jd| jdS )NTrZ   shuffler[   )r   r\   rZ   r[   r/   r   r   r   train_dataloader   
   zSyn3DLightning.train_dataloaderc                 C   rf   NFrg   )r   r]   rZ   r[   r/   r   r   r   val_dataloader   rj   zSyn3DLightning.val_dataloaderc                 C   rf   rk   )r   r^   rZ   r[   r/   r   r   r   test_dataloader   rj   zSyn3DLightning.test_dataloader)r2   rX   r   r&   )
rS   rT   rU   rV   r-   re   ri   rl   rm   __classcell__r   r   r_   r   rW      s    	
rW   )r   )r   )r
   r   r@   torch.utils.datar   r   torchvisionr   pytorch_lightningplr   Zsklearn.model_selectionr   ZnibabelrK   Zutils.image_processingr   r   r#   r$   LightningDataModulerW   r   r   r   r   <module>   s    

a