o
    z3i3                     @   s  d dl Z d dlmZmZ d dlmZ d dlmZmZm	Z	m
Z
mZmZ d dlZddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZ erTd dlZddlmZ ejred dlZG dd dej j!Z"eG dd dZ#dddde$de%e&eee&e'f  f fddZ(dS )    N)	dataclassfield)Path)TYPE_CHECKINGAnyClassVarDictOptionalUnion   )config)DownloadConfig)
array_cast)is_local_pathxopen)no_op_if_value_is_nullstring_to_dict   )FeatureTypec                       s2   e Zd ZdZdejjf fddZdd Z  Z	S )Nifti1ImageWrapperzY
        A wrapper around nibabel's Nifti1Image to customize its representation.
        nifti_imagec                    s0   t  j|j|j|j|j|j| d || _d S )N)dataobjaffineheaderextrafile_mapdtype)	super__init__r   r   r   r   r   get_data_dtyper   )selfr   	__class__ e/lsinfo/ai/hellotax_ai/llm_service/venv_embed/lib/python3.10/site-packages/datasets/features/nifti.pyr      s   
zNifti1ImageWrapper.__init__c           
      C   s   ddl m}m}m}m} ddlm} | j }| }|	|j
 |j|j_d|j_d|j_d }t| jdrNd| jjv rNt| jjd dd d urN| jjd j}|d u rTd}|||d	}	||	g || d S )
Nr   )NiiVue
ShowRender	SliceTypeVolume)displayTr   imagefilenamezvolume.nii.gz)namedata)	ipyniivuer%   r&   r'   r(   IPython.displayr)   r   to_bytesset_slice_typeMULTIPLANARALWAYSoptsmultiplanar_show_rendershow_3d_crosshairmultiplanar_force_renderhasattrr   getattrr+   load_volumes)
r    r%   r&   r'   r(   r)   bytes_nvr,   volumer#   r#   r$   _repr_html_'   s$   

zNifti1ImageWrapper._repr_html_)
__name__
__module____qualname____doc__nibnifti1Nifti1Imager   r>   __classcell__r#   r#   r!   r$   r      s    r   c                   @   s  e Zd ZU dZdZeed< edddZe	e
 ed< dZee
 ed	< ee e d
Zee ed< ed dddZe
ed< dd Zdee
eeedf defddZd deddfddZd dejdejfddZdedee
df f fddZdeejejej f dejfddZ!dS )!Niftia  
    **Experimental.**
    Nifti [`Feature`] to read NIfTI neuroimaging files.

    Input: The Nifti feature accepts as input:
    - A `str`: Absolute path to the NIfTI file (i.e. random access is allowed).
    - A `pathlib.Path`: path to the NIfTI file (i.e. random access is allowed).
    - A `dict` with the keys:
        - `path`: String with relative path of the NIfTI file in a dataset repository.
        - `bytes`: Bytes of the NIfTI file.
      This is useful for archived files with sequential access.

    - A `nibabel` image object (e.g., `nibabel.nifti1.Nifti1Image`).

    Args:
        decode (`bool`, defaults to `True`):
            Whether to decode the NIfTI data. If `False` a string with the bytes is returned. `decode=False` is not supported when decoding examples.

    Examples:

    ```py
    >>> from datasets import Dataset, Nifti
    >>> ds = Dataset.from_dict({"nifti": ["path/to/file.nii.gz"]}).cast_column("nifti", Nifti())
    >>> ds.features["nifti"]
    Nifti(decode=True, id=None)
    >>> ds[0]["nifti"]
    <nibabel.nifti1.Nifti1Image object at 0x7f8a1c2d8f40>
    >>> ds = ds.cast_column("nifti", Nifti(decode=False))
    >>> ds[0]["nifti"]
    {'bytes': None,
    'path': 'path/to/file.nii.gz'}
    ```
    TdecodeNF)defaultrepridznibabel.nifti1.Nifti1Imager   bytespathpa_type)rI   initrJ   _typec                 C   s   | j S N)rO   )r    r#   r#   r$   __call__k   s   zNifti.__call__valuenib.Nifti1Imagereturnc                 C   s  t jrddl}nd}t|tr|ddS t|tr"t| ddS t|ttfr.d|dS |dur=t||j	j
r=t|S t|trz|ddurYtj|d rYd|ddS |ddusg|ddurr|d|ddS td| dtd	t| d)
zEncode example into a format for Arrow.

        Args:
            value (`str`, `bytes`, `nibabel.Nifti1Image` or `dict`):
                Data passed as input to Nifti feature.

        Returns:
            `dict` with "path" and "bytes" fields
        r   NrN   rM   rN   rL   rM   zTA nifti sample should have one of 'path' or 'bytes' but they are missing or None in .zPA nifti sample should be a string, bytes, Path, nibabel image, or dict, but got )r   NIBABEL_AVAILABLEnibabel
isinstancestrr   absoluterM   	bytearrayspatialimagesSpatialImageencode_nibabel_imagedictgetosrN   isfile
ValueErrortype)r    rT   rC   r#   r#   r$   encode_examplen   s,   







zNifti.encode_exampler   c                 C   sj  t jrddl}ntd|du ri }|d |d }}|du r|du r+td| d|dr@t|d	d
 r@|d	d
 }t|rM||}t|S |d	d
 }|t j	r]t j
nt j}t||}	|	durp||	d nd}
t|
d}t|d|d}||}W d   t|S 1 sw   Y  t|S ddl}|dd dkr||}|j|}t|S )a  Decode example NIfTI file into nibabel image object.

        Args:
            value (`str` or `dict`):
                A string with the absolute NIfTI file path, a dictionary with
                keys:

                - `path`: String with absolute or relative NIfTI file path.
                - `bytes`: The bytes of the NIfTI file.

            token_per_repo_id (`dict`, *optional*):
                To access and decode NIfTI files from private repositories on
                the Hub, you can pass a dictionary
                repo_id (`str`) -> token (`bool` or `str`).

        Returns:
            `nibabel.Nifti1Image` objects
        r   Nz:To support decoding NIfTI files, please install 'nibabel'.rN   rM   zBA nifti should have one of 'path' or 'bytes' but both are None in rX   zgzip://::repo_idtokenrbdownload_configr   s   )r   rY   rZ   ImportErrorrf   
startswithr   splitloadHF_ENDPOINTHUB_DATASETS_URLHUB_DATASETS_HFFS_URLr   rc   r   r   gzip
decompressrE   
from_bytesr   )r    rT   token_per_repo_idrC   rN   r;   nifti
source_urlpatternsource_url_fieldsrm   rp   frx   r#   r#   r$   decode_example   sD   






zNifti.decode_examplestoragec                    s   du ri t fdd tj fdd| D t d}tjdd |d D t d}tjj||gd	dg|	 d
}t
|| jS )a8  Embed NifTI files into the Arrow array.

        Args:
            storage (`pa.StructArray`):
                PyArrow array to embed.

        Returns:
            `pa.StructArray`: Array in the NifTI arrow storage type, that is
                `pa.struct({"bytes": pa.binary(), "path": pa.string()})`.
        Nc                    s   |  dd }|tjrtjntj}t||}|d ur# |d nd }t|d}t	| d|d}|
 W  d    S 1 s@w   Y  d S )Nri   rj   rk   rl   rn   ro   )rs   rr   r   ru   rv   rw   r   rc   r   r   read)rN   r}   r~   r   rm   rp   r   )r{   r#   r$   path_to_bytes   s   

$z*Nifti.embed_storage.<locals>.path_to_bytesc                    s8   g | ]}|d ur|d d u r |d n|d nd qS )NrM   rN   r#   ).0x)r   r#   r$   
<listcomp>   s    *z'Nifti.embed_storage.<locals>.<listcomp>rg   c                 S   s$   g | ]}|d urt j|nd qS rR   )rd   rN   basename)r   rN   r#   r#   r$   r      s   $ rN   rM   mask)r   paarray	to_pylistbinaryr   stringStructArrayfrom_arraysis_nullr   rO   )r    r   r{   bytes_array
path_arrayr#   )r   r{   r$   embed_storage   s    
zNifti.embed_storager   c                 C   s(   ddl m} | jr| S |d|ddS )zfIf in the decodable state, return the feature itself, otherwise flatten the feature into a dictionary.r   )Valuer   r   rL   )featuresr   rH   )r    r   r#   r#   r$   flatten   s   zNifti.flattenc                 C   s<  t j|jr%t jdgt| t  d}t jj||gddg|	 d}nst j
|jrJt jdgt| t  d}t jj||gddg|	 d}nNt j|jr|jddkr_|d}nt jdgt| t  d}|jddkr{|d}nt jdgt| t  d}t jj||gddg|	 d}t|| jS )a  Cast an Arrow array to the Nifti arrow storage type.
        The Arrow types that can be converted to the Nifti pyarrow storage type are:

        - `pa.string()` - it must contain the "path" data
        - `pa.binary()` - it must contain the NIfTI bytes
        - `pa.struct({"bytes": pa.binary()})`
        - `pa.struct({"path": pa.string()})`
        - `pa.struct({"bytes": pa.binary(), "path": pa.string()})`  - order doesn't matter

        Args:
            storage (`Union[pa.StringArray, pa.StructArray, pa.BinaryArray]`):
                PyArrow array to cast.

        Returns:
            `pa.StructArray`: Array in the Nifti arrow storage type, that is
                `pa.struct({"bytes": pa.binary(), "path": pa.string()})`.
        Nr   rM   rN   r   r   )r   types	is_stringrg   r   lenr   r   r   r   	is_binaryr   	is_structget_field_indexr   r   rO   )r    r   r   r   r#   r#   r$   cast_storage
  s     zNifti.cast_storagerR   )"r?   r@   rA   rB   rH   bool__annotations__r   rK   r	   r\   r   r   r   structr   r   rO   r   rQ   rS   r
   rM   r^   rb   rh   r   r   r   r   r   StringArrayBinaryArrayr   r#   r#   r#   r$   rG   ?   s   
 "$ (?((rG   FimgrU   force_bytesrV   c                 C   s@   t | dr| jdur|s| jd j}|ddS |  }d|dS )a  
    Encode a nibabel image object into a dictionary.

    If the image has an associated file path, returns the path. Otherwise, serializes
    the image content into bytes.

    Args:
        img: A nibabel image object (e.g., Nifti1Image).
        force_bytes: If `True`, always serialize to bytes even if a file path exists. Needed to upload bytes properly.

    Returns:
        dict: A dictionary with "path" or "bytes" field.
    r   Nr*   rW   )r8   r   r+   r0   )r   r   r+   
bytes_datar#   r#   r$   ra   /  s
   

ra   )F))rd   dataclassesr   r   pathlibr   typingr   r   r   r   r	   r
   pyarrowr    r   download.download_configr   tabler   utils.file_utilsr   r   utils.py_utilsr   r   rZ   rC   r   r   rY   rD   rE   r   rG   r   rb   r\   rM   ra   r#   r#   r#   r$   <module>   s(     ( 0p