o
    i                 	   @   s  U d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
mZmZmZmZmZ ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZmZmZmZmZmZm Z  zddl!Z!W n	 e"yj   Y nw ddl#Z#dd
l#m$Z$m%Z% ddl&m'Z' ddl(m)Z)m*Z* ddl+m,Z, ddl-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 ddl4m5Z5m6Z6m7Z7 ddl8m9Z9m:Z: ddl;m<Z<m=Z= ddl>m?Z? ddl@mAZAmBZBmCZCmDZD ddlEmFZFmGZGmHZH ddlImJZJmKZKmLZLmMZMmNZN ddlOmPZPmQZQ ddlRmSZTmUZU ddlVmWZX h dZYG dd dZZd2dddede[e\ dB d e]fd!d"Z^e5e7B Z_d#Z`eead$< G d%d dZbed&d'd(ZcG d)d' d'ebZd	*d3d+d,d-e]d dfd.d/ZeG d0d, d,ebZfegd1ZhdS )4a  Define the Dataset and FileDataset classes.

The Dataset class represents the DICOM Dataset while the FileDataset class
adds extra functionality to Dataset when data is read from or written to file.

Overview of DICOM object model
------------------------------
Dataset (dict subclass)
  Contains DataElement instances, each of which has a tag, VR, VM and value.
    The DataElement value can be:
        * A single value, such as a number, string, etc. (i.e. VM = 1)
        * A list of numbers, strings, etc. (i.e. VM > 1)
        * A Sequence (list subclass), where each item is a Dataset which
            contains its own DataElements, and so on in a recursive manner.
    N)bisect_left)
ValuesViewIteratorCallableMutableSequenceMutableMappingSet)nullcontext)	find_spec)	takewhile)TracebackType)	TypeAliasAnyAnyStrcastBinaryIOTypeVaroverload)jsonrepconfig)__version_info__)default_encodingconvert_encodings)logger)dictionary_descriptiondictionary_VRtag_for_keywordkeyword_for_tagrepeater_has_keywordget_private_entry)DataElementconvert_raw_data_elementRawDataElement)ReadableBufferWriteableBuffer)path_from_pathlikePathType)warn_and_log)compressconvert_color_space
decompresspixel_array)reshape_pixel_arrayget_image_pixel_idsset_pixel_data)TagBaseTagtag_in_exceptionTagType
TAG_PIXREP)PYDICOM_IMPLEMENTATION_UIDUID)VRAMBIGUOUS_VR)numpy_handler>    	  c                   @   s   e Zd ZdZdeeef dddeddfdd	Zd
edefddZ	d
ede
fddZd
edefddZd
eddfddZd
edededdfddZdedd fddZdS )PrivateBlockay  Helper class for a private block in the :class:`Dataset`.

    See the DICOM Standard, Part 5,
    :dcm:`Section 7.8.1<part05/sect_7.8.html#sect_7.8.1>` - Private Data
    Element Tags

    Attributes
    ----------
    group : int
        The private group where the private block is located as a 32-bit
        :class:`int`.
    private_creator : str
        The private creator string related to the block.
    dataset : Dataset
        The parent dataset.
    block_start : int
        The start element of the private block as a 32-bit :class:`int`. Note
        that the 2 low order hex digits of the element are always 0.
    keydatasetDatasetprivate_creator_elementreturnNc                 C   s(   |d | _ |d | _|| _|d> | _dS )a  Initializes an object corresponding to a private tag block.

        Parameters
        ----------
        key : tuple
            The private (tag group, creator) as ``(int, str)``. The group
            must be an odd number.
        dataset : Dataset
            The parent :class:`Dataset`.
        private_creator_element : int
            The element of the private creator tag as a 32-bit :class:`int`.
        r         N)groupprivate_creatorr>   block_start)selfr=   r>   r@    rH   E/mnt/sdb/aimis/docanh/lib/python3.10/site-packages/pydicom/dataset.py__init__i   s   

zPrivateBlock.__init__element_offsetc                 C   s"   |dkrt dt| j| j| S )a  Return the private tag ID for the given `element_offset`.

        Parameters
        ----------
        element_offset : int
            The lower 16 bits (e.g. 2 hex numbers) of the element tag.

        Returns
        -------
            The tag ID defined by the private block location and the
            given element offset.

        Raises
        ------
        ValueError
            If `element_offset` is too large.
           z$Element offset must be less than 256)
ValueErrorr/   rD   rF   rG   rK   rH   rH   rI   get_tag}   s   zPrivateBlock.get_tagc                 C   s   |  || jv S )zjReturn ``True`` if the tag with given `element_offset` is in
        the parent :class:`Dataset`.
        )rO   r>   rN   rH   rH   rI   __contains__   s   zPrivateBlock.__contains__c                 C   s   | j | |S )a=  Return the data element in the parent dataset for the given element
        offset.

        Parameters
        ----------
        element_offset : int
            The lower 16 bits (e.g. 2 hex numbers) of the element tag.

        Returns
        -------
            The data element of the tag in the parent dataset defined by the
            private block location and the given element offset.

        Raises
        ------
        ValueError
            If `element_offset` is too large.
        KeyError
            If no data element exists at that offset.
        )r>   __getitem__rO   rN   rH   rH   rI   rQ      s   zPrivateBlock.__getitem__c                 C   s   | j | |= dS )a  Delete the tag with the given `element_offset` from the dataset.

        Parameters
        ----------
        element_offset : int
            The lower 16 bits (e.g. 2 hex numbers) of the element tag
            to be deleted.

        Raises
        ------
        ValueError
            If `element_offset` is too large.
        KeyError
            If no data element exists at that offset.
        N)r>   rO   rN   rH   rH   rI   __delitem__   s   zPrivateBlock.__delitem__r6   valuec                 C   s,   |  |}| j||| | j| j| _dS )aX  Add a private element to the parent :class:`Dataset`.

        Adds the private tag with the given `VR` and `value` to the parent
        :class:`Dataset` at the tag ID defined by the private block and the
        given `element_offset`.

        Parameters
        ----------
        element_offset : int
            The lower 16 bits (e.g. 2 hex numbers) of the element tag
            to be added.
        VR : str
            The 2 character DICOM value representation.
        value
            The value of the data element. See :meth:`Dataset.add_new()`
            for a description.
        N)rO   r>   add_newrE   )rG   rK   r6   rS   tagrH   rH   rI   rT      s   
zPrivateBlock.add_newmemoc                 C   s.   |  | j| jf| j| jd? }||t| < |S )NrC   )	__class__rD   rE   r>   rF   id)rG   rV   copiedrH   rH   rI   __deepcopy__   s   
zPrivateBlock.__deepcopy__)__name__
__module____qualname____doc__tupleintstrrJ   r0   rO   boolrP   r    rQ   rR   objectrT   r   rZ   rH   rH   rH   rI   r<   T   s"    

r<   ar?   bexcluderA   c                    sH   t  t ko#tfdd  D o#t fdd  D S )a  Common method for Dataset.__eq__ and FileDataset.__eq__

    Uses .keys() as needed because Dataset iter return items not keys
    `exclude` is used in FileDataset__eq__ ds.__dict__ compare, which
    would also compare the wrapped _dict member (entire dataset) again.
    c                 3   s    | ]}| v V  qd S NrH   .0r=   )re   rH   rI   	<genexpr>   s    z_dict_equal.<locals>.<genexpr>c                 3   s0    | ]}d u s|vr | | kV  qd S rg   rH   rh   rd   re   rf   rH   rI   rj      s    )lenallkeysrk   rH   rk   rI   _dict_equal   s   ro   z0Dataset | MutableMapping[BaseTag, _DatasetValue]_DatasetTypec                       s	  e Zd ZdZdZdededdfddZdd	d
Zde	e
 dB de
dB dedB dedB fddZdeddfddZdedededdfddZ	ddedededededB ddfddZddd Zd!ededB fd"d#Zd!edefd$d%Zdd&d'Zdd(d)Zd!eddfd*d+Zdd.d/Zdee f fd0d1Zd2edee fd3d4Zd5edefd6d7Ze dd,ed8edB defd9d:Z!e 	dd,ee"eef B e#B d8edB defd;d:Z!	dd,eeB e"eef B e#B d8edB deeB fd<d:Z!de$e"e#e%f  fd=d>Z&de$e# fd?d@Z'de(e% fdAdBZ)d!edefdCdDZ*e+deee B fdEdFZ,e+dee-e B fdGdHZ.e+dee-e B fdIdJZ/e/j0dee-e B ddfdKdJZ/e d,e1dd fdLdMZ2e d,edefdNdMZ2ddQdMZ2	RddededSede3fdTdUZ4dedee fdVdWZ5dedededefdXdYZ6e dZd[d,e1d\edd fd]d^Z7e dZd[d,ed\edefd_d^Z7dRd[d,dOd\edd`fdad^Z7dbe1dd fdcddZ8e+dedB fdedfZ9e9j0dedB ddfdgdfZ9e+dedB fdhdiZ:e:j0dedB ddfdjdiZ:e+defdkdlZ;e+de"eef e"dm B fdndoZ<	ddpedB dqedB dree-e B dB ddfdsdtZ=dedd fdudvZ>de?e fdwdxZ@de?eeAB  fdydzZBdefd{d|ZCd5edefd}d~ZDdddZEd,ddede%fddZFde"e#e%f fddZGdd,ed8edB defddZHd	deddfddZId!eddfddZJdddZKdeddfddZL			Rd
ddddddedddededededB deeM dB deeM dB deddfddZN	d	dddddedededededdfddZOdeddfddZPe+dddZQddRddRddedB dededededdfddZRdeddfddZSdZTdZUeTeUdfdedededB de?e fddZVddededefddZWe+dedB fddZXe+dedB fddZYdddZZ	ddddRdddedB dee[j\e] B e^B e_B dedB dedB dedededdfddʄZ`ddd̄Zad!ededdfdd΄ZbdddфZcd,dOde%ddfddԄZddd՜dddedededdf
ddلZededdfddۄZfdddddedB dee# fddZgdefddZhdefddZidee fddZjdeddfddZkde?e fddZl	ddemd egdf deddfddZneo	dde	d  depeef eB eqB erB demeeegdeB eB eMB eqB f emegdeB eB eMB eqB f B dB dd fddZs			Rddedemegef dB dedepeef fddZt				Rddedemegef dB demepeef gef dB dedef
ddZuddddededB deqdB ddfd dZvehZw  ZxS (  r?   a:  A DICOM dataset as a mutable mapping of DICOM Data Elements.

    Examples
    --------
    Add an element to the :class:`Dataset` (for elements in the DICOM
    dictionary):

    >>> ds = Dataset()
    >>> ds.PatientName = "CITIZEN^Joan"
    >>> ds.add_new(0x00100020, 'LO', '12345')
    >>> ds[0x0010, 0x0030] = DataElement(0x00100030, 'DA', '20010101')

    Add a sequence element to the :class:`Dataset`

    >>> ds.BeamSequence = [Dataset(), Dataset(), Dataset()]
    >>> ds.BeamSequence[0].Manufacturer = "Linac, co."
    >>> ds.BeamSequence[1].Manufacturer = "Linac and Sons, co."
    >>> ds.BeamSequence[2].Manufacturer = "Linac and Daughters, co."

    Add private elements to the :class:`Dataset`

    >>> block = ds.private_block(0x0041, 'My Creator', create=True)
    >>> block.add_new(0x01, 'LO', '12345')

    Updating and retrieving element values:

    >>> ds.PatientName = "CITIZEN^Joan"
    >>> ds.PatientName
    'CITIZEN^Joan'
    >>> ds.PatientName = "CITIZEN^John"
    >>> ds.PatientName
    'CITIZEN^John'

    Retrieving an element's value from a Sequence:

    >>> ds.BeamSequence[0].Manufacturer
    'Linac, co.'
    >>> ds.BeamSequence[1].Manufacturer
    'Linac and Sons, co.'

    Accessing the :class:`~pydicom.dataelem.DataElement` items:

    >>> elem = ds['PatientName']
    >>> elem
    (0010,0010) Patient's Name                      PN: 'CITIZEN^John'
    >>> elem = ds[0x00100010]
    >>> elem
    (0010,0010) Patient's Name                      PN: 'CITIZEN^John'
    >>> elem = ds.data_element('PatientName')
    >>> elem
    (0010,0010) Patient's Name                      PN: 'CITIZEN^John'

    Accessing a private :class:`~pydicom.dataelem.DataElement`
    item:

    >>> block = ds.private_block(0x0041, 'My Creator')
    >>> elem = block[0x01]
    >>> elem
    (0041,1001) Private tag data                    LO: '12345'
    >>> elem.value
    '12345'

    Alternatively:

    >>> ds.get_private_item(0x0041, 0x01, 'My Creator').value
    '12345'

    Deleting an element from the :class:`Dataset`

    >>> del ds.PatientID
    >>> del ds.BeamSequence[1].Manufacturer
    >>> del ds.BeamSequence[2]

    Deleting a private element from the :class:`Dataset`

    >>> block = ds.private_block(0x0041, 'My Creator')
    >>> if 0x01 in block:
    ...     del block[0x01]

    Determining if an element is present in the :class:`Dataset`

    >>> 'PatientName' in ds
    True
    >>> 'PatientID' in ds
    False
    >>> (0x0010, 0x0030) in ds
    True
    >>> 'Manufacturer' in ds.BeamSequence[0]
    True

    Iterating through the top level of a :class:`Dataset` only (excluding
    Sequences):

    >>> for elem in ds:
    ...    print(elem)
    (0010,0010) Patient's Name                      PN: 'CITIZEN^John'

    Iterating through the entire :class:`Dataset` (including Sequences):

    >>> for elem in ds.iterall():
    ...     print(elem)
    (0010,0010) Patient's Name                      PN: 'CITIZEN^John'

    Recursively iterate through a :class:`Dataset` (including Sequences):

    >>> def recurse(ds):
    ...     for elem in ds:
    ...         if elem.VR == 'SQ':
    ...             [recurse(item) for item in elem.value]
    ...         else:
    ...             # Do something useful with each DataElement

    Converting the :class:`Dataset` to and from JSON:

    >>> ds = Dataset()
    >>> ds.PatientName = "Some^Name"
    >>> jsonmodel = ds.to_json()
    >>> ds2 = Dataset()
    >>> ds2.from_json(jsonmodel)
    (0010,0010) Patient's Name                      PN: 'Some^Name'

    Attributes
    ----------
    default_element_format : str
        The default formatting for string display.
    default_sequence_element_format : str
        The default formatting for string display of sequences.
    indent_chars : str
        For string display, the characters used to indent nested Sequences.
        Default is ``"   "``.
    z   argskwargsrA   Nc                 O   s   | dt| _|  |si | _nt|d tr|d j| _n|d | _d| _d| _d| _d| _	t
js7d| _d| _d| _i | _d| _ddi| _i | _|  |  dS )z'Create a new :class:`Dataset` instance.parent_encodingr   FN use_pdh)getr   _parent_encoding_dict
isinstancer?   is_decompressed_read_little_read_implicit_read_charsetr   _use_future_is_little_endian_is_implicit_VR!is_undefined_length_sequence_item_private_blocks_pixel_array_pixel_array_opts	_pixel_idrG   rq   rr   rH   rH   rI   rJ     s.   

zDataset.__init__c                 C   s   | S )z,Method invoked on entry to a with statement.rH   rG   rH   rH   rI   	__enter__     zDataset.__enter__exc_typeexc_valexc_tbc                 C   s   dS )z-Method invoked on exit from a with statement.NrH   )rG   r   r   r   rH   rH   rI   __exit__  s   zDataset.__exit__data_elementc                 C   s   || |j < dS )a  Add an element to the :class:`Dataset`.

        Equivalent to ``ds[data_element.tag] = data_element``

        Parameters
        ----------
        data_element : dataelem.DataElement
            The :class:`~pydicom.dataelem.DataElement` to add.
        N)rU   )rG   r   rH   rH   rI   add  s   
zDataset.addrU   r6   rS   c                 C   s   |  t||| dS )a8  Create a new element and add it to the :class:`Dataset`.

        Parameters
        ----------
        tag
            The DICOM (group, element) tag in any form accepted by
            :func:`~pydicom.tag.Tag` such as ``[0x0010, 0x0010]``,
            ``(0x10, 0x10)``, ``0x00100010``, etc.
        VR : str
            The 2 character DICOM value representation (see DICOM Standard,
            Part 5, :dcm:`Section 6.2<part05/sect_6.2.html>`).
        value
            The value of the data element. One of the following:

            * a single string or number
            * a :class:`list` or :class:`tuple` with all strings or all numbers
            * a multi-value string with backslash separator
            * for a sequence element, an empty :class:`list` or ``list`` of
              :class:`Dataset`
        N)r   r    )rG   rU   r6   rS   rH   rH   rI   rT     s   zDataset.add_newrE   rD   rK   vrc                 C   s<   | j ||dd}|du rt||f|d }|||| dS )a4  Create a new private element and add it to the :class:`Dataset`.

        Parameters
        ----------
        private_creator : str
            The private creator string related to the new tag.
        group : int
            The group ID (0x0009 - 0xFFFF) for the private tag.
            Must be an odd number.
        element_offset : int
            The tag offset, e.g. the lower byte of the tag element of the
            private tag (0x00 - 0xFF). The higher byte is defined by the location
            of the private creator tag.
        value : Any
            The value of the data element. One of the following:

            * a single string or number
            * a :class:`list` or :class:`tuple` with all strings or all numbers
            * a multi-value string with backslash separator
            * for a sequence element, an empty :class:`list` or ``list`` of
              :class:`Dataset`
        vr : str | None
            The two-letter DICOM value representation, or ``None``.
            If set to ``None``, it is taken from the private tag dictionary.

        Raises
        ------
        ValueError
            If `group` doesn't belong to a private tag or `private_creator` is empty.
        KeyError
            If `vr` is ``None`` and the tag is not found in the private tag dictionary.
        T)createNr   )private_blockr   rT   )rG   rE   rD   rK   rS   r   blockrH   rH   rI   add_new_private  s   (zDataset.add_new_privatenumpy.ndarrayc                 C   s   t | jS )z1Support accessing the dataset from a numpy array.)numpyasarrayrx   r   rH   rH   rI   	__array__     zDataset.__array__namec                 C   s   t |}|dur| | S dS )a  Return the element corresponding to the element keyword `name`.

        Parameters
        ----------
        name : str
            A DICOM element keyword.

        Returns
        -------
        dataelem.DataElement or None
            For the given DICOM element `keyword`, return the corresponding
            :class:`~pydicom.dataelem.DataElement` if present, ``None``
            otherwise.
        N)r   rG   r   rU   rH   rH   rI   r     s   zDataset.data_elementc              
   C   s   zt || jv W S  tyC } z/d| d}t|trd}tjdkr't| ntjdkr1t||W Y d}~dS W Y d}~dS d}~ww )a  Simulate dict.__contains__() to handle DICOM keywords.

        Examples
        --------

        >>> ds = Dataset()
        >>> ds.SliceLocation = '2'
        >>> 'SliceLocation' in ds
        True

        Parameters
        ----------
        name : str or int or 2-tuple
            The element keyword or tag to search for.

        Returns
        -------
        bool
            ``True`` if the corresponding element is in the :class:`Dataset`,
            ``False`` otherwise.
        zInvalid value 'z`' used with the 'in' operator: must be an element tag as a 2-tuple or int, or an element keywordzdInvalid element tag value used with the 'in' operator: tags have a maximum value of (0xFFFF, 0xFFFF)WARNRAISENF)	r/   rx   	Exceptionry   OverflowErrorr   INVALID_KEY_BEHAVIORr'   rM   )rG   r   excmsgrH   rH   rI   rP   )  s$   







zDataset.__contains__c                    s<   | j tjj dddtddf fdd}| j|dd	 dS )
zApply character set decoding to the elements in the
        :class:`Dataset`.

        See DICOM Standard, Part 5,
        :dcm:`Section 6.1.1<part05/chapter_6.html#sect_6.1.1>`.
        dsr?   r   rA   Nc                    s8   |j tjkr|jD ]	}|_|  q	dS  | dS )z"Callback to decode `data_element`.N)r6   VR_SQrS   rw   decode)r   r   dsetdecode_data_elementdicom_character_setrH   rI   decode_callbackc  s   

z'Dataset.decode.<locals>.decode_callbackF)	recursive)_character_setpydicomcharsetdecode_elementr    walk)rG   r   rH   r   rI   r   S  s   		zDataset.decodec                 C   s
   t  | S )z%Return a shallow copy of the dataset.)copyr   rH   rH   rI   r   n     
zDataset.copyc                 C   sb   t tt|}|dur"|| jv r"| j|= |tv r d| _i | _dS dS || jv r-| j|= dS t|)a  Intercept requests to delete an attribute by `name`.

        Examples
        --------

        >>> ds = Dataset()
        >>> ds.PatientName = 'foo'
        >>> ds.some_attribute = True

        If `name` is a DICOM keyword - delete the corresponding
        :class:`~pydicom.dataelem.DataElement`

        >>> del ds.PatientName
        >>> 'PatientName' in ds
        False

        If `name` is another attribute - delete it

        >>> del ds.some_attribute
        >>> hasattr(ds, 'some_attribute')
        False

        Parameters
        ----------
        name : str
            The keyword for the DICOM element or the class attribute to delete.
        N)	r   r0   r   rx   PIXEL_KEYWORDSr   r   __dict__AttributeErrorr   rH   rH   rI   __delattr__r  s   

zDataset.__delattr__r=   slice | BaseTag | TagTypec                 C   s   t |tr-| |j|j|jD ]}| j|= | jr t|j	r i | _|t
v r*d| _i | _qdS t |trM| j|= | jr?|j	r?i | _|t
v rKd| _i | _dS dS t|}| j|= | jr^|j	r^i | _|t
v rjd| _i | _dS dS )a  Intercept requests to delete an attribute by key.

        Examples
        --------
        Indexing using :class:`~pydicom.dataelem.DataElement` tag

        >>> ds = Dataset()
        >>> ds.CommandGroupLength = 100
        >>> ds.PatientName = 'CITIZEN^Jan'
        >>> del ds[0x00000000]
        >>> ds
        (0010,0010) Patient's Name                      PN: 'CITIZEN^Jan'

        Slicing using :class:`~pydicom.dataelem.DataElement` tag

        >>> ds = Dataset()
        >>> ds.CommandGroupLength = 100
        >>> ds.SOPInstanceUID = '1.2.3'
        >>> ds.PatientName = 'CITIZEN^Jan'
        >>> del ds[:0x00100000]
        >>> ds
        (0010,0010) Patient's Name                      PN: 'CITIZEN^Jan'

        Parameters
        ----------
        key
            The key for the attribute to be deleted. If a ``slice`` is used
            then the tags matching the slice conditions will be deleted.
        N)ry   slice_slice_datasetstartstopsteprx   r   r0   is_private_creatorr   r   r   r/   )rG   r=   rU   rH   rH   rI   rR     s4   




zDataset.__delitem__c                    s&   t t  }t |  }t||B S )zReturn a list of methods, properties, attributes and element
        keywords available in the :class:`Dataset`.

        List of attributes is used, for example, in auto-completion in editors
        or command-line environments.
        )setsuper__dir__dirsorted)rG   nameskeywordsrW   rH   rI   r     s   zDataset.__dir__filtersc                    sv   dd | j  D }dd |D }i }|D ]     fdd|D }|dd |D  q|r7t| S t|S )a  Return an alphabetical list of element keywords in the
        :class:`Dataset`.

        Intended mainly for use in interactive Python sessions. Only lists the
        element keywords in the current level of the :class:`Dataset` (i.e.
        the contents of any sequence elements are ignored).

        Parameters
        ----------
        filters : str
            Zero or more string arguments to the function. Used for
            case-insensitive match to any part of the DICOM keyword.

        Returns
        -------
        list of str
            The matching element keywords in the dataset. If no
            filters are used then all element keywords are returned.
        c                 S      g | ]}t |qS rH   )r   ri   rU   rH   rH   rI   
<listcomp>      zDataset.dir.<locals>.<listcomp>c                 S   s   g | ]}|r|qS rH   rH   ri   xrH   rH   rI   r      r   c                    s"   g | ]}|   d kr|qS ))lowerfindr   filter_rH   rI   r     s   " c                 S   s   i | ]}|d qS rB   rH   r   rH   rH   rI   
<dictcomp>      zDataset.dir.<locals>.<dictcomp>)rx   rn   r   updater   )rG   r   allnamesmatchesmatchrH   r   rI   r     s   zDataset.dirotherc                 C   s&   || u rdS t || jrt| |S tS )ae  Compare `self` and `other` for equality.

        Returns
        -------
        bool
            The result if `self` and `other` are the same class
        NotImplemented
            If `other` is not the same class as `self` then returning
            :class:`NotImplemented` delegates the result to
            ``superclass.__eq__(subclass)``.
        T)ry   rW   ro   NotImplementedrG   r   rH   rH   rI   __eq__  s
   
zDataset.__eq__defaultc                 C      d S rg   rH   rG   r=   r   rH   rH   rI   rv   "  r   zDataset.getc                 C   r   rg   rH   r   rH   rH   rI   rv   &  s   c              
   C   s   t |trzt| |W S  ty   | Y S w zt|}W n ty. } ztd|d}~ww z| |W S  ty@   | Y S w )a5  Simulate ``dict.get()`` to handle element tags and keywords.

        Parameters
        ----------
        key : str or int or Tuple[int, int] or BaseTag
            The element keyword or tag or the class attribute name to get.
        default : obj or None, optional
            If the element or class attribute is not present, return
            `default` (default ``None``).

        Returns
        -------
        value
            If `key` is the keyword for an element in the :class:`Dataset`
            then return the element's value.
        dataelem.DataElement
            If `key` is a tag for a element in the :class:`Dataset` then
            return the :class:`~pydicom.dataelem.DataElement`
            instance.
        value
            If `key` is a class attribute then return its value.
        z'Dataset.get key must be a string or tagN)	ry   ra   getattrr   r/   r   	TypeErrorrQ   KeyError)rG   r=   r   r   rH   rH   rI   rv   ,  s"   

c                 C   
   | j  S )a  Return the :class:`Dataset` items to simulate :meth:`dict.items`.

        Returns
        -------
        dict_items
            The top-level (:class:`~pydicom.tag.BaseTag`,
            :class:`~pydicom.dataelem.DataElement`) items for the
            :class:`Dataset`.
        )rx   itemsr   rH   rH   rI   r   W  s   

zDataset.itemsc                 C   r   )zReturn the :class:`Dataset` keys to simulate :meth:`dict.keys`.

        Returns
        -------
        dict_keys
            The :class:`~pydicom.tag.BaseTag` of all the elements in
            the :class:`Dataset`.
        )rx   rn   r   rH   rH   rI   rn   c     
	zDataset.keysc                 C   r   )a   Return the :class:`Dataset` values to simulate :meth:`dict.values`.

        Returns
        -------
        dict_keys
            The :class:`DataElements<pydicom.dataelem.DataElement>` that make
            up the values of the :class:`Dataset`.
        )rx   valuesr   rH   rH   rI   r   n  r   zDataset.valuesc                 C   sD   t |}|durt|}|| jv r| | jS |dkri S t| |S )a	  Intercept requests for :class:`Dataset` attribute names.

        If `name` matches a DICOM keyword, return the value for the
        element with the corresponding tag.

        Parameters
        ----------
        name : str
            An element keyword or a class attribute name.

        Returns
        -------
        value
              If `name` matches a DICOM keyword, returns the corresponding
              element's value. Otherwise returns the class attribute's
              value (if present).
        Nrx   )r   r/   rx   rS   rc   __getattribute__r   rH   rH   rI   __getattr__y  s   

zDataset.__getattr__c                 C   s$   |  tdd}|s| jS t|jS )z-The character set used to encode text values.  N)rv   r0   rw   r   rS   )rG   char_setrH   rH   rI   r     s   
zDataset._character_setc                 C   s   | j S )a  Return the original character set encoding for a dataset decoded
        from a file or buffer.

        Returns
        -------
        str | MutableSequence[str]
            The original character set encoding of the dataset as given by
            the (0008,0005) *Specific Character Set*, or `iso8859
            <https://docs.python.org/3/library/codecs.html#standard-encodings>`_
            if the dataset has been created from scratch.
        )r}   r   rH   rH   rI   original_character_set  s   zDataset.original_character_setc                 C   >   t | j}tjrtd| dtd| d| dt | jS )zReturn the original character set encoding for a decoded dataset.

        .. deprecated:: 3.0

            ``read_encoding`` will be removed in v4.0, use
            :attr:`~pydicom.dataset.Dataset.original_character_set` instead.

        ')' object has no attribute 'read_encoding'..read_encoding' will be removed in v4.0, use ' .original_character_set' instead)typer[   r   r~   r   r'   DeprecationWarningr   rG   r   rH   rH   rI   read_encoding  s   

zDataset.read_encodingc                 C   B   t | j}tjrtd| dtd| d| dt || _d S )Nr   r   r   r   )r   r[   r   r~   r   r'   r   r}   rG   rS   r   rH   rH   rI   r     s   

c                 C   r   rg   rH   rG   r=   rH   rH   rI   rQ     r   zDataset.__getitem__c                 C   r   rg   rH   r   rH   rH   rI   rQ     r   slice | TagTypeDataset | DataElementc           	   
   C   s`  t |tr
| |S t |tr|}nzt|}W n ty- } z	td| d|d}~ww | j| }t |tr|j	du rg|j
dkrgddlm} | jpM| j}| jr^| jr^t| jdds^| j}|| j|| j|}|tdkrt| jpr| j}nt}t||| d| |< | | jtjkr| | |  | | jtv rdd	lm} || | | |d
 | |< tt| j|S )a!  Operator for ``Dataset[key]`` request.

        Any deferred data elements will be read in and an attempt will be made
        to correct any elements with ambiguous VRs.

        Examples
        --------
        Indexing using :class:`~pydicom.dataelem.DataElement` tag

        >>> ds = Dataset()
        >>> ds.SOPInstanceUID = '1.2.3'
        >>> ds.PatientName = 'CITIZEN^Jan'
        >>> ds.PatientID = '12345'
        >>> ds[0x00100010].value
        'CITIZEN^Jan'

        Slicing using element tags; all group ``0x0010`` elements in
        the  dataset

        >>> ds[0x00100000:0x00110000]
        (0010,0010) Patient's Name                      PN: 'CITIZEN^Jan'
        (0010,0020) Patient ID                          LO: '12345'

        All group ``0x0002`` elements in the dataset

        >>> ds[(0x0002, 0x0000):(0x0003, 0x0000)]
        <BLANKLINE>

        Parameters
        ----------
        key
            The DICOM (group, element) tag in any form accepted by
            :func:`~pydicom.tag.Tag` such as ``[0x0010, 0x0010]``,
            ``(0x10, 0x10)``, ``0x00100010``, etc. May also be a :class:`slice`
            made up of DICOM tags.

        Returns
        -------
        dataelem.DataElement or Dataset
            If a single DICOM element tag is used then returns the
            corresponding :class:`~pydicom.dataelem.DataElement`.
            If a :class:`slice` is used then returns a :class:`Dataset` object
            containing the corresponding
            :class:`DataElements<pydicom.dataelem.DataElement>`.
        r   Nr   )read_deferred_data_elementclosedFr   encodingr   )correct_ambiguous_vr_element   ) ry   r   _dataset_slicer0   r/   r   r   rx   r"   rS   lengthpydicom.filereaderr   filenamebufferr   fileobj_type	timestampr   r   r   r!   r6   r   r   _set_pixel_representationr7   pydicom.filewriterr   r   r    rv   )	rG   r=   rU   r   elemr   srccharacter_setr   rH   rH   rI   rQ     sF   
0



Fr   c                    s   dt dtffdd} fjv rj S s td d dkr*td d	f d
f }tfdd|D d}|durJ||jjS |sTtd dt fddtd	d
D }	t
 |d ||S )a  Return the block for the given tag `group` and `private_creator`.

        If `create` is ``True`` and the `private_creator` does not exist,
        the private creator tag is added.

        Notes
        -----
        We ignore the unrealistic case that no free block is available.

        Parameters
        ----------
        group : int
            The group of the private tag to be found as a 32-bit :class:`int`.
            Must be an odd number (e.g. a private group).
        private_creator : str
            The private creator string associated with the tag.
        create : bool, optional
            If ``True`` and `private_creator` does not exist, a new private
            creator tag is added at the next free block. If ``False``
            (the default) and `private_creator` does not exist,
            :class:`KeyError` is raised instead.

        Returns
        -------
        PrivateBlock
            The existing or newly created private block.

        Raises
        ------
        ValueError
            If `group` doesn't belong to a private tag or `private_creator`
            is empty.
        KeyError
            If the private creator tag is not found in the given group and
            the `create` parameter is ``False``.
        elementrA   c                    s   t  | }|j < |S rg   )r<   r   )r  r   )r=   rG   rH   rI   	new_blockk  s   
z(Dataset.private_block.<locals>.new_blockz!Private creator must have a value   r   z/Tag must be private if private creator is given      c                 3   s    | ]
}|j  kr|V  qd S rg   rS   )ri   r
  )rE   rH   rI   rj   |  s    z(Dataset.private_block.<locals>.<genexpr>NzPrivate creator 'z' not foundc                 3   s$    | ]}t  |jvr|V  qd S rg   )r/   rx   )ri   el)rD   rG   rH   rI   rj     s    LO)r`   r<   r   rM   nextrU   r  r   rangerT   r/   )rG   rD   rE   r   r  r   data_elfirst_free_elrH   )rD   r=   rE   rG   rI   r   C  s&   (

zDataset.private_blockc                 C   s6   |d dkr
t d| |df|df }dd |D S )a  Return a list of private creator names in the given group.

        Examples
        --------
        This can be used to check if a given private creator exists in
        the group of the dataset:

        >>> ds = Dataset()
        >>> if 'My Creator' in ds.private_creators(0x0041):
        ...     block = ds.private_block(0x0041, 'My Creator')

        Parameters
        ----------
        group : int
            The private group as a 32-bit :class:`int`. Must be an odd number.

        Returns
        -------
        list of str
            All private creator names for private blocks in the group.

        Raises
        ------
        ValueError
            If `group` is not a private group.
        r  r   zGroup must be an odd numberr  r  c                 S   s   g | ]}|j qS rH   r  r   rH   rH   rI   r     r   z,Dataset.private_creators.<locals>.<listcomp>)rM   )rG   rD   r   rH   rH   rI   private_creators  s   zDataset.private_creatorsc                 C   s   |  ||}| ||S )a.  Return the data element for the given private tag `group`.

        This is analogous to ``Dataset.__getitem__()``, but only for private
        tags. This allows to find the private tag for the correct private
        creator without the need to add the tag to the private dictionary
        first.

        Parameters
        ----------
        group : int
            The private tag group where the item is located as a 32-bit int.
        element_offset : int
            The lower 16 bits (e.g. 2 hex numbers) of the element tag.
        private_creator : str
            The private creator for the tag. Must match the private creator
            for the tag to be returned.

        Returns
        -------
        dataelem.DataElement
            The corresponding element.

        Raises
        ------
        ValueError
            If `group` is not part of a private tag or `private_creator` is
            empty.
        KeyError
            If the private creator tag is not found in the given group.
            If the private tag is not found.
        )r   rQ   rO   )rG   rD   rK   rE   r   rH   rH   rI   get_private_item  s   "zDataset.get_private_item.)keep_deferredr  c                C   r   rg   rH   rG   r=   r  rH   rH   rI   get_item  r   zDataset.get_itemc                C   r   rg   rH   r  rH   rH   rI   r    r   z-Dataset | DataElement | RawDataElement | Nonec                C   sH   t |tr
| |S | jt|}t |tr"|s"|jdu r"| | S |S )a  Return the raw data element if possible.

        It will be raw if the user has never accessed the value, or set their
        own value. Note if the data element is a deferred-read element,
        then it is read and converted before being returned.

        .. versionchanged: 3.0

            Added the `keep_deferred` keyword argument.

        Parameters
        ----------
        key
            The DICOM (group, element) tag in any form accepted by
            :func:`~pydicom.tag.Tag` such as ``[0x0010, 0x0010]``,
            ``(0x10, 0x10)``, ``0x00100010``, etc. May also be a :class:`slice`
            made up of DICOM tags.
        keep_deferred : bool, optional
            If ``True`` then when returning :class:`~pydicom.dataelem.RawDataElement`
            do not perform the deferred read of the element's value (accessing
            the value will return ``None`` instead). Default ``False``.

        Returns
        -------
        dataelem.DataElement | dataelem.RawDataElement
            The corresponding element.
        N)ry   r   r  rx   rv   r/   r"   rS   )rG   r=   r  r
  rH   rH   rI   r    s   
!

slcec                    s^     |j|j|j}t fdd|D } j\}}||| j tj	s- j
|_ j|_|S )a  Return a slice that has the same properties as the original dataset.

        That includes properties related to endianness and VR handling,
        and the specific character set. No element conversion is done, e.g.
        elements of type ``RawDataElement`` are kept.
        c                    s   i | ]}|  |qS rH   )r  r   r   rH   rI   r         z*Dataset._dataset_slice.<locals>.<dictcomp>)r   r   r   r   r?   original_encodingset_original_encodingr   r   r~   is_little_endianr   is_implicit_VRr   )rG   r  tagsr   is_implicit	is_littlerH   r   rI   r  	  s   
zDataset._dataset_slicec                 C   "   t jrtdt| j d| jS )a:  Get/set the VR method used when encoding the dataset.

        .. deprecated:: 3.0

            ``is_implicit_VR`` will be removed in v4.0, set the *Transfer
            Syntax UID* or use the `implicit_vr` argument with
            :meth:`~pydicom.dataset.Dataset.save_as` or
            :func:`~pydicom.filewriter.dcmwrite` instead.

        Returns
        -------
        bool | None
            If the dataset has been created from scratch then returns ``None``,
            otherwise returns the VR encoding method used by the decoded
            dataset.
        r   *' object has no attribute 'is_implicit_VR')r   r~   r   r   r[   r   r   rH   rH   rI   r#    
   zDataset.is_implicit_VRc                 C   r   )Nr   r(  zm.is_implicit_VR' will be removed in v4.0, set the Transfer Syntax UID or use the 'implicit_vr' argument with  .save_as() or dcmwrite() instead)r   r[   r   r~   r   r'   r   r   r   rH   rH   rI   r#  3     

c                 C   r'  )aG  Get/set the endianness used when encoding the dataset.

        .. deprecated:: 3.0

            ``is_little_endian`` will be removed in v4.0, set the *Transfer
            Syntax UID* or use the `little_endian` argument with
            :meth:`~pydicom.dataset.Dataset.save_as` or
            :func:`~pydicom.filewriter.dcmwrite` instead.

        Returns
        -------
        bool | None
            If the dataset has been created from scratch then returns ``None``,
            otherwise returns the endianness of the encoding used by the
            decoded dataset.
        r   ,' object has no attribute 'is_little_endian')r   r~   r   r   r[   r   r   rH   rH   rI   r"  C  r)  zDataset.is_little_endianc                 C   r   )Nr   r,  zq.is_little_endian' will be removed in v4.0, set the Transfer Syntax UID or use the 'little_endian' argument with r*  )r   r[   r   r~   r   r'   r   r   r   rH   rH   rI   r"  \  r+  c                 C   s<   t jr	| j| jkS | j| jf}d|vo| j|ko| j| jkS )a  Return ``True`` if the encoding to be used for writing is set and
        is the same as that used to originally encode the  :class:`Dataset`.

        This includes properties related to endianness, VR handling and the
        (0008,0005) *Specific Character Set*.
        N)r   r~   r   r   r#  r"  r   )rG   current_encodingrH   rH   rI   is_original_encodingl  s   
zDataset.is_original_encodingNNc                 C   s"   t tttf td B | j| jfS )a  Return the original encoding used for a dataset decoded from a file
        or buffer.

        Returns
        -------
        tuple[bool, bool] | tuple[None, None]
            For a dataset decoded from a file or buffer this is whether
            the encoding used implicit/explicit VR and little/big endian
            as ``(encoded as implicit VR, encoded as little endian)``. Returns
            ``(None, None)`` for a dataset created from scratch.
        r/  )r   r_   rb   r|   r{   r   rH   rH   rI   r   ~  s   
zDataset.original_encodingis_implicit_vrr"  character_encodingc                 C   s"   || _ || _|dur|| _dS dS )a  Set the values for the original dataset encoding.

        Can be used for a :class:`Dataset` with raw data elements to enable
        optimized writing (e.g. without decoding the data elements).

        .. versionchanged:: 3.0

            `character_encoding` is now optional

        Parameters
        ----------
        is_implicit_vr : bool | None
            The the original VR encoding of the dataset, ``True`` for implicit
            VR, ``False`` for explicit VR or ``None`` to reset.
        is_little_endian : bool | None
            Set the original endianness of the dataset, ``True`` for little
            endian, ``False`` for big or ``None`` to reset.
        character_encoding : str | MutableSequence[str], optional
            Set the original character set encoding of the dataset. If ``None``
            then no changes will be made to the original character set
            encoding.
        N)r|   r{   r}   )rG   r0  r"  r1  rH   rH   rI   r!    s
   
zDataset.set_original_encodingc                 C   s   | |df|d df S )aJ  Return a :class:`Dataset` containing only elements of a certain
        group.

        Parameters
        ----------
        group : int
            The group part of a DICOM (group, element) tag.

        Returns
        -------
        Dataset
            A :class:`Dataset` containing elements of the group specified.
        r   rB   rH   )rG   rD   rH   rH   rI   group_dataset  s   zDataset.group_datasetc                 c   s(    t | j }|D ]}| | V  q
dS )a  Iterate through the top-level of the Dataset, yielding DataElements.

        Examples
        --------

        >>> ds = Dataset()
        >>> for elem in ds:
        ...     print(elem)

        The :class:`DataElements<pydicom.dataelem.DataElement>` are returned in
        increasing tag value order. Sequence items are returned as a single
        :class:`~pydicom.dataelem.DataElement`, so it is up
        to the calling code to recurse into the Sequence items if desired.

        Yields
        ------
        dataelem.DataElement
            The :class:`Dataset`'s
            :class:`DataElements<pydicom.dataelem.DataElement>`, sorted by
            increasing tag order.
        N)r   rx   rn   rG   taglistrU   rH   rH   rI   __iter__  s
   zDataset.__iter__c                 c   s*    t | j }|D ]}| |V  q
dS )a  Yield the top-level elements of the :class:`Dataset`.

        Examples
        --------

        >>> ds = Dataset()
        >>> for elem in ds.elements():
        ...     print(elem)

        The elements are returned in the same way as in
        ``Dataset.__getitem__()``.

        Yields
        ------
        dataelem.DataElement or dataelem.RawDataElement
            The unconverted elements sorted by increasing tag order.
        N)r   rx   rn   r  r3  rH   rH   rI   elements  s
   zDataset.elementsc                 C   s
   t | jS )z>Return the number of elements in the top level of the dataset.)rl   rx   r   rH   rH   rI   __len__  r   zDataset.__len__c                 C   s
   | |k S )z*Compare `self` and `other` for inequality.rH   r   rH   rH   rI   __ne__  r   zDataset.__ne__c                 C   s   | j   dS )z2Delete all the elements from the :class:`Dataset`.N)rx   clearr   rH   rH   rI   r9    s   zDataset.clearzBaseTag | TagTypec                 G   s:   zt |}W n	 ty   Y nw | jjtt|g|R  S )a  Emulate :meth:`dict.pop` with support for tags and keywords.

        Removes the element for `key` if it exists and returns it,
        otherwise returns a default value if given or raises :class:`KeyError`.

        Parameters
        ----------
        key : int or str or 2-tuple

            * If :class:`tuple` - the group and element number of the DICOM tag
            * If :class:`int` - the combined group/element number
            * If :class:`str` - the DICOM keyword of the tag

        *args : zero or one argument
            Defines the behavior if no tag exists for `key`: if given,
            it defines the return value, if not given, :class:`KeyError` is
            raised

        Returns
        -------
        RawDataElement or DataElement
            The element for `key` if it exists, or the default value if given.

        Raises
        ------
        KeyError
            If the `key` is not a valid tag or keyword.
            If the tag does not exist and no default is given.
        )r/   r   rx   popr   r0   )rG   r=   rq   rH   rH   rI   r:     s   zDataset.popc                 C   r   )zoEmulate :meth:`dict.popitem`.

        Returns
        -------
        tuple of (BaseTag, DataElement)
        )rx   popitemr   rH   rH   rI   r;  %  s   
zDataset.popitemc                 C   s   t |}|| v r| | S t|tsG|jrtj}n)zt|}W n" ty@   tj	j
tjkr3td| tj}td| d Y nw t|||}|| |< |S )a  Emulate :meth:`dict.setdefault` with support for tags and keywords.

        Examples
        --------

        >>> ds = Dataset()
        >>> elem = ds.setdefault((0x0010, 0x0010), "Test")
        >>> elem
        (0010,0010) Patient's Name                      PN: 'Test'
        >>> elem.value
        'Test'
        >>> elem = ds.setdefault('PatientSex',
        ...     DataElement(0x00100040, 'CS', 'F'))
        >>> elem.value
        'F'

        Parameters
        ----------
        key : int, str or 2-tuple of int

            * If :class:`tuple` - the group and element number of the DICOM tag
            * If :class:`int` - the combined group/element number
            * If :class:`str` - the DICOM keyword of the tag
        default : pydicom.dataelem.DataElement or object, optional
            The :class:`~pydicom.dataelem.DataElement` to use with `key`, or
            the value of the :class:`~pydicom.dataelem.DataElement` to use with
            `key` (default ``None``).

        Returns
        -------
        pydicom.dataelem.DataElement or object
            The :class:`~pydicom.dataelem.DataElement` for `key`.

        Raises
        ------
        ValueError
            If `key` is not convertible to a valid tag or a known element
            keyword.
        KeyError
            If :attr:`~pydicom.config.settings.reading_validation_mode` is
             ``RAISE`` and `key` is an unknown non-private tag.
        zUnknown DICOM tag z - setting VR to 'UN')r/   ry   r    
is_privater   UNr   r   r   settingswriting_validation_moder   r'   )rG   r=   r   rU   r   rH   rH   rI   
setdefault.  s"   +
zDataset.setdefaultrt   handler_namec                 C   s   t jrtdt| j dd}t| dsd}n| jdu rd}| jt| kr(d}|r,dS | j	
 }|r7| n|dd}|d	 sU||d< t| fi || _t| | _dS |r^| | dS |   dS )
a  Convert pixel data to a :class:`numpy.ndarray` internally.

        .. deprecated:: 3.0

            This method will be removed in v4.0, use
            :meth:`~pydicom.dataset.Dataset.pixel_array_options` instead.

        Parameters
        ----------
        handler_name : str, optional
            The name of the pixel handler or decoding plugin to use to decode
            the dataset's pixel data. Support values are:

            * If using the :mod:`~pydicom.pixel_data_handlers` backend:
              ``'gdcm'``, ``'pillow'``, ``'jpeg_ls'``, ``'rle'``, ``'numpy'``
              and ``'pylibjpeg'``.
            * If using the :mod:`~pydicom.pixels` backend see the
              :doc:`documentation for the decoder</reference/pixels.decoders>`
              corresponding to the dataset's *Transfer Syntax UID*.

            If not used (the default) then all available handlers or plugins
            will be tried and the data from first successful one will be
            used.

        Returns
        -------
        None
            Converted pixel data is stored internally in the dataset, it can
            be accessed with the :attr:`~pydicom.dataset.Dataset.pixel_array`
            property.

        Raises
        ------
        ValueError
            If `handler_name` is not a valid handler name.
        NotImplementedError
            If the given handler or any handler, if none given, is unable to
            decompress pixel data with the current transfer syntax
        RuntimeError
            If the given handler, or the handler that has been selected if
            none given, is not available.

        Notes
        -----
        If the pixel data is in a compressed image format, the data is
        decompressed and any related data elements are changed accordingly.
        r   z.' object has no attribute 'convert_pixel_data'Tr   FNdecoding_pluginrt   ru   )r   r~   r   r   r[   hasattrr   r   r-   r   r   r   rv   r+   !_convert_pixel_data_using_handler#_convert_pixel_data_without_handler)rG   rA  already_haveoptsr   rH   rH   rI   convert_pixel_dataq  s,   1


zDataset.convert_pixel_datac                 C   s   |  }|ds|d7 }|dkrd}|dkrd}ttj|s'td| dttj|}| jj}|	|sEt
d| d	|j d
| d| sQtd| d| | dS )zConvert the pixel data using handler with the given name.
        See :meth:`~Dataset.convert_pixel_data` for more information.
        _handlerr8   
np_handlerjpeg_ls_handlerjpegls_handlerr   z' is not a known handler name;Unable to decode pixel data with a transfer syntax UID of '' (z ) using the pixel data handler 'zW'. Please see the pydicom documentation for information on supported transfer syntaxes.zThe pixel data handler 'z{' is not available on your system. Please refer to the pydicom documentation for information on installing needed packages.N)r   endswithrC  r   r   rM   r   	file_metaTransferSyntaxUIDsupports_transfer_syntaxNotImplementedErrorr   is_availableRuntimeError_do_pixel_data_conversion)rG   r   rA  handlertsyntaxrH   rH   rI   rD    s4   


z)Dataset._convert_pixel_data_using_handlerc                    s:  | j jfddtjjD }|std dj ddd |D }|sZd}g }|D ]$}|j dd  D } fd	d|D }||j	 d
d
| d q,t|d
| d}|D ]&}	z	| |	 W  dS  ty }
 ztjd|
d |
}W Y d}
~
q^d}
~
ww d| _i | _tdd
dd |D  |)zConvert the pixel data using the first matching handler.
        See :meth:`~Dataset.convert_pixel_data` for more information.
        c                    s"   g | ]}|d ur|  r|qS rg   )rR  ri   hh)tsrH   rI   r     s
    z?Dataset._convert_pixel_data_without_handler.<locals>.<listcomp>rM  rN  z) as there are no pixel data handlers available that support it. Please see the pydicom documentation for information on supported transfer syntaxes c                 S   s   g | ]}|  r|qS rH   )rT  rY  rH   rH   rI   r     r  znThe following handlers are available to decode the pixel data however they are missing required dependencies: c                 S   s   g | ]
}t |d u r|qS rg   )have_package)ri   ddrH   rH   rI   r     s    c                    s   g | ]} | d  qS r   rH   )ri   r   )hh_depsrH   rI   r     r  z (req. , )Nz&Exception raised by pixel data handler)exc_infozUnable to decode the pixel data using the following handlers: {}.Please see the list of supported Transfer Syntaxes in the pydicom documentation for alternative packages that might be able to decode the datac                 S   r   rH   )ra   rY  rH   rH   rI   r   -  r   )rP  rQ  r   r   pixel_data_handlersrS  r   DEPENDENCIESappendHANDLER_NAMEjoinrU  rV  r   r   debugr   r   infoformat)rG   possible_handlersavailable_handlersr   pkg_msgrZ  missingr   last_exceptionrW  r   rH   )r^  r[  rI   rE    sT   
	 
z+Dataset._convert_pixel_data_without_handlerrW  c                 C   s>   | | }t| || _|| rt| jdd| _t| | _dS )z6Do the actual data conversion using the given handler.YBR_FULLRGBN)get_pixeldatar,   r   needs_to_convert_to_RGBr)   r-   r   )rG   rW  arrrH   rH   rI   rV  2  s   

z!Dataset._do_pixel_data_conversionT)generate_instance_uid	jls_errorj2k_crj2k_psnrtransfer_syntax_uidrs  znumpy.ndarray | Noneencoding_pluginencapsulate_extrt  ru  rv  rw  c          
   	   K   s&   t | ||f||||||d|	 dS )a  Compress uncompressed pixel data and update `ds` in-place with the
        resulting :dcm:`encapsulated<part05/sect_A.4.html>` codestream.

        .. versionadded:: 2.2

        The dataset `ds` must already have the following
        :dcm:`Image Pixel<part03/sect_C.7.6.3.html>` module elements present
        with correct values that correspond to the resulting compressed
        pixel data:

        * (0028,0002) *Samples per Pixel*
        * (0028,0004) *Photometric Interpretation*
        * (0028,0008) *Number of Frames* (if more than 1 frame will be present)
        * (0028,0010) *Rows*
        * (0028,0011) *Columns*
        * (0028,0100) *Bits Allocated*
        * (0028,0101) *Bits Stored*
        * (0028,0103) *Pixel Representation*

        If *Samples per Pixel* is greater than 1 then the following element
        is also required:

        * (0028,0006) *Planar Configuration*

        This method will add the file meta dataset if none is present and add
        or modify the following elements:

        * (0002,0010) *Transfer Syntax UID*
        * (7FE0,0010) *Pixel Data*

        If the compressed pixel data is too large for encapsulation using a
        basic offset table then an :dcm:`extended offset table
        <part03/sect_C.7.6.3.html>` will also be used, in which case the
        following elements will also be added:

        * (7FE0,0001) *Extended Offset Table*
        * (7FE0,0002) *Extended Offset Table Lengths*

        If `generate_instance_uid` is ``True`` (default) then a new (0008,0018) *SOP
        Instance UID* value will be generated.

        **Supported Transfer Syntax UIDs**

        +-----------------------------------------------+-----------+----------------------------------+
        | UID                                           |  Plugins  | Encoding Guide                   |
        +------------------------+----------------------+           |                                  |
        | Name                   | Value                |           |                                  |
        +========================+======================+===========+==================================+
        |*JPEG-LS Lossless*      |1.2.840.10008.1.2.4.80| pyjpegls  | :doc:`JPEG-LS                    |
        +------------------------+----------------------+           | </guides/encoding/jpeg_ls>`      |
        | *JPEG-LS Near Lossless*|1.2.840.10008.1.2.4.81|           |                                  |
        +------------------------+----------------------+-----------+----------------------------------+
        | *JPEG 2000 Lossless*   |1.2.840.10008.1.2.4.90| pylibjpeg | :doc:`JPEG 2000                  |
        +------------------------+----------------------+           | </guides/encoding/jpeg_2k>`      |
        | *JPEG 2000*            |1.2.840.10008.1.2.4.91|           |                                  |
        +------------------------+----------------------+-----------+----------------------------------+
        | *RLE Lossless*         | 1.2.840.10008.1.2.5  | pydicom,  | :doc:`RLE Lossless               |
        |                        |                      | pylibjpeg,| </guides/encoding/rle_lossless>` |
        |                        |                      | gdcm      |                                  |
        +------------------------+----------------------+-----------+----------------------------------+

        .. versionchanged:: 3.0

            Added the `jls_error`, `j2k_cr`, `j2k_psnr` and `generate_instance_uid`
            keyword parameters.

        Examples
        --------

        Compress the existing uncompressed *Pixel Data* in place:

        >>> from pydicom import examples
        >>> from pydicom.uid import RLELossless
        >>> ds = examples.ct
        >>> ds.compress(RLELossless)
        >>> ds.save_as("ct_rle_lossless.dcm")

        Parameters
        ----------
        transfer_syntax_uid : pydicom.uid.UID
            The UID of the :dcm:`transfer syntax<part05/chapter_10.html>` to
            use when compressing the pixel data.
        arr : numpy.ndarray, optional
            Compress the uncompressed pixel data in `arr` and use it
            to set the *Pixel Data*. If `arr` is not used then the
            existing *Pixel Data* in the dataset will be compressed instead.
            The :attr:`~numpy.ndarray.shape`, :class:`~numpy.dtype` and
            contents of the array should match the dataset.
        encoding_plugin : str, optional
            Use the `encoding_plugin` to compress the pixel data. See the
            :doc:`user guide </guides/user/image_data_compression>` for a list of
            plugins available for each UID and their dependencies. If not
            specified then all available plugins will be tried (default).
        encapsulate_ext : bool, optional
            If ``True`` then force the addition of an extended offset table.
            If ``False`` (default) then an extended offset table
            will be added if needed for large amounts of compressed *Pixel
            Data*, otherwise just the basic offset table will be used.
        generate_instance_uid : bool, optional
            If ``True`` (default) then generate a new (0008,0018) *SOP Instance UID*
            value for the dataset using :func:`~pydicom.uid.generate_uid`, otherwise
            keep the original value.
        jls_error : int, optional
            **JPEG-LS Near Lossless only**. The allowed absolute compression error
            in the pixel values.
        j2k_cr : list[float], optional
            **JPEG 2000 only**. A list of the compression ratios to use for each
            quality layer. There must be at least one quality layer and the
            minimum allowable compression ratio is ``1``. When using multiple
            quality layers they should be ordered in decreasing value from left
            to right. For example, to use 2 quality layers with 20x and 5x
            compression ratios then `j2k_cr` should be ``[20, 5]``. Cannot be
            used with `j2k_psnr`.
        j2k_psnr : list[float], optional
            **JPEG 2000 only**. A list of the peak signal-to-noise ratios (in dB)
            to use for each quality layer. There must be at least one quality
            layer and when using multiple quality layers they should be ordered
            in increasing value from left to right. For example, to use 2
            quality layers with PSNR of 80 and 300 then `j2k_psnr` should be
            ``[80, 300]``. Cannot be used with `j2k_cr`.
        **kwargs
            Optional keyword parameters for the encoding plugin may also be
            present. See the :doc:`encoding plugins options
            </guides/encoding/encoder_plugin_options>` for more information.
        )ry  rz  rt  ru  rv  rw  N)r(   )
rG   rx  rs  ry  rz  rt  ru  rv  rw  rr   rH   rH   rI   r(   C  s    

zDataset.compress)as_rgbrt  rB  r{  rB  c                K   sr   t jr|d|rtt| j d| j }|r||d< |r$||d< |jdi | t	| f||d| dS )a  Perform an in-place decompression of a dataset with a compressed *Transfer
        Syntax UID*.

        .. warning::

            This function requires `NumPy <https://numpy.org/>`_ and may require
            the installation of additional packages to perform the actual pixel
            data decoding. See the :doc:`pixel data decompression documentation
            </guides/user/image_data_handlers>` for more information.

        * The dataset's *Transfer Syntax UID* will be set to *Explicit
          VR Little Endian*.
        * The *Pixel Data* will be decompressed in its entirety and the
          *Pixel Data* element's value updated with the decompressed data,
          padded to an even length.
        * The *Pixel Data* element's VR will be set to **OB** if *Bits
          Allocated* <= 8, otherwise it will be set to **OW**.
        * The :attr:`DataElement.is_undefined_length
          <pydicom.dataelem.DataElement.is_undefined_length>` attribute for the
          *Pixel Data* element will be set to ``False``.
        * Any :dcm:`image pixel<part03/sect_C.7.6.3.html>` module elements may be
          modified as required to match the uncompressed *Pixel Data*.
        * If `generate_instance_uid` is ``True`` (default) then a new (0008,0018) *SOP
          Instance UID* value will be generated.

        .. versionchanged:: 3.0

            Added the `as_rgb` and `generate_instance_uid` keyword parameters.

        .. deprecated:: 3.0

            The `handler_name` parameter will be removed in v4.0, use
            `decoding_plugin` instead.

        Parameters
        ----------
        handler_name : str, optional
            Deprecated and will be removed in v4.0, use `decoding_plugin` instead.
        as_rgb : bool, optional
            :mod:`~pydicom.pixels` **backend only.** If ``True`` (default) then
            convert pixel data with a YCbCr :ref:`photometric interpretation
            <photometric_interpretation>` such as ``"YBR_FULL_422"`` to RGB.
        generate_instance_uid : bool, optional
            If ``True`` (default) then generate a new (0008,0018) *SOP Instance UID*
            value for the dataset using :func:`~pydicom.uid.generate_uid`, otherwise
            keep the original value.
        decoding_plugin : str, optional
            The name of the decoding plugin to use when decoding compressed
            pixel data. If no `decoding_plugin` is specified (default) then all
            available plugins will be tried and the result from the first successful
            one yielded.

            * If using the :mod:`~pydicom.pixels` backend (default) then see the
              :doc:`API documentation</reference/pixels.decoders>` for the available
              plugins for each *Transfer Syntax UID*.
            * If using the deprecated :mod:`~pydicom.pixel_data_handlers` backend
              supported plugins are: ``'gdcm'``, ``'pillow'``, ``'jpeg_ls'``,
              ``'rle'``, ``'numpy'`` and ``'pylibjpeg'``.
        kwargs : dict[str, Any], optional
            :mod:`~pydicom.pixels` **backend only.** Optional keyword parameters
            for the decoding plugin may also be present. See the :doc:`decoding
            plugins options</guides/decoding/decoder_options>` for more information.
        rA  z?.decompress() got an unexpected keyword argument 'handler_name'rB  )r{  rt  NrH   )
r   r~   rv   r   r   r[   r   r   r   r*   )rG   rA  r{  rt  rB  rr   rG  rH   rH   rI   r*     s$   I

zDataset.decompressc                 C   sJ   |dk s|dkrt dtjstdt| j dddlm} || |S )aO  Return the *Overlay Data* in `group` as a :class:`numpy.ndarray`.

        Parameters
        ----------
        group : int
            The group number of the overlay data.

        Returns
        -------
        numpy.ndarray
            The (`group`,3000) *Overlay Data* converted to a
            :class:`numpy.ndarray`.
        i `  i`  z^The group part of the 'Overlay Data' element tag must be between 0x6000 and 0x60FF (inclusive)zNumPy is required for z.overlay_array()r   )get_overlay_array)rM   r   
have_numpyImportErrorr   r[   pydicom.overlaysr|  )rG   rD   r|  rH   rH   rI   overlay_array8  s   
zDataset.overlay_arrayc                 C   s   |    td| jS )a
  Return the pixel data as a :class:`numpy.ndarray`.

        .. warning::

            This property requires `NumPy <https://numpy.org/>`_ and may require
            the installation of additional packages to perform the actual pixel
            data decoding. See the :doc:`pixel data decompression documentation
            </guides/user/image_data_handlers>` for more information.

        .. versionchanged:: 3.0

            The backend used for pixel data decoding has changed from the
            :mod:`~pydicom.pixel_data_handlers` module to the
            :mod:`~pydicom.pixels` module. The behavior of the new backend
            is not backwards compatible with the old one, in particular the
            default color space should now be RGB when previously YCbCr data
            was returned.

            To revert to the deprecated :mod:`~pydicom.pixel_data_handlers`
            backend pass ``use_v2_backend=True`` to the
            :meth:`~pydicom.dataset.Dataset.pixel_array_options` method::

                >>> from pydicom import examples
                >>> ds = examples.ct
                >>> ds.pixel_array_options(use_v2_backend=True)
                >>> arr = ds.pixel_array

            The :mod:`~pydicom.pixel_data_handlers` module and the
            `use_v2_backend` keyword argument will be removed in v4.0.

        Returns
        -------
        numpy.ndarray
            The contents of the (7FE0,0008) *Float Pixel Data*, (7FE0,0009)
            *Double Float Pixel Data* or (7FE0,0010) *Pixel Data* elements
            converted to a :class:`numpy.ndarray`. The array will be shaped as:

            * (rows, columns) for single frame, single sample data
            * (rows, columns, samples) for single frame, multi-sample data
            * (frames, rows, columns) for multi-frame, single sample data
            * (frames, rows, columns, samples) for multi-frame, multi-sample data

            When using the :mod:`pydicom.pixels` backend the decoding options
            used with the returned array can be customized via the
            :meth:`~pydicom.dataset.Dataset.pixel_array_options` method.

        See Also
        --------
        pydicom.pixels.pixel_array
            A function for returning the pixel data from the path to a dataset,
            a readable file-like containing a dataset or a
            :class:`~pydicom.dataset.Dataset` instance. Can be used to minimize
            the memory required to return the pixel data when used with a path
            or file-like.
        pydicom.pixels.iter_pixels
            Similar to :func:`pydicom.pixels.pixel_array` but returns a generator
            that iterates through the image frames.
        r   )rH  r   r   r   rH   rH   rI   r+   U  s   <zDataset.pixel_array)indexrawrB  use_v2_backendr  r  r  c                K   sn   t jr|d|rtt| j d||d< ||d< |r#| |d< t jr(dn||d< || _d| _i | _	dS )	a  Set the decoding and processing options used by the
        :attr:`~pydicom.dataset.Dataset.pixel_array` property.

        .. versionadded:: 3.0

        .. deprecated:: 3.0

            The `use_v2_backend` keyword parameter will be removed in v4.0.

        **Processing**

        The following processing operations on the raw pixel data will always
        be performed:

        * Natively encoded bit-packed pixel data for a :ref:`bits allocated
          <bits_allocated>` of ``1`` will be unpacked.
        * Natively encoded pixel data with a :ref:`photometric interpretation
          <photometric_interpretation>` of ``"YBR_FULL_422"`` will
          have it's sub-sampling removed.
        * The output array will be reshaped to the specified dimensions.
        * JPEG-LS or JPEG 2000 encoded data whose signedness doesn't match the
          expected :ref:`pixel representation<pixel_representation>` will be
          converted to match.

        With the :mod:`pydicom.pixels` backend, if ``raw = False`` (the
        default) then the following processing operation will also be performed:

        * Pixel data with a :ref:`photometric interpretation
          <photometric_interpretation>` of ``"YBR_FULL"`` or ``"YBR_FULL_422"``
          will be converted to RGB.

        Examples
        --------

        Convert the *Pixel Data* to an array that's a view on the original buffer::

            >>> from pydicom import examples
            >>> ds = examples.ct
            >>> ds.pixel_array_options(view_only=True)
            >>> arr = ds.pixel_array

        Use the deprecated :mod:`~pydicom.pixel_data_handlers` backend to convert
        the *Pixel Data* to an array::

            >>> from pydicom import examples
            >>> ds = examples.ct
            >>> ds.pixel_array_options(use_v2_backend=True)
            >>> arr = ds.pixel_array

        Parameters
        ----------
        index : int | None, optional
            If ``None`` (default) then return an array containing all the
            frames in the pixel data, otherwise return one containing only
            the frame from the specified `index`, which starts at 0 for the
            first frame. Only available with the :mod:`~pydicom.pixels` backend.
        raw : bool, optional
            If ``True`` then return the decoded pixel data after only
            minimal processing (see the processing section above). If ``False``
            (default) then additional processing may be applied to convert the
            pixel data to it's most commonly used form (such as converting from
            YCbCr to RGB). Only available with the :mod:`~pydicom.pixels` backend.
        decoding_plugin : str, optional
            The name of the decoding plugin to use when decoding compressed
            pixel data. If no `decoding_plugin` is specified (default) then all
            available plugins will be tried and the result from the first successful
            one returned. For information on the available plugins for each
            *Transfer Syntax UID*:

            * If using the :mod:`~pydicom.pixels` backend see the
              :doc:`documentation for the decoder</reference/pixels.decoders>`
              corresponding to the dataset's *Transfer Syntax UID*.
            * If using the :mod:`~pydicom.pixel_data_handlers` backend supported
              values are  ``'gdcm'``, ``'pillow'``, ``'jpeg_ls'``, ``'rle'``,
              ``'numpy'`` and ``'pylibjpeg'``.
        use_v2_backend : bool, optional
            If ``False`` (default) then use the :mod:`pydicom.pixels` backend
            to decode the pixel data, otherwise use the deprecated
            :mod:`pydicom.pixel_data_handlers` backend.
        **kwargs
            Optional keyword parameters for controlling decoding with the
            :mod:`~pydicom.pixels` backend, please see the
            :doc:`decoding options documentation</guides/decoding/decoder_options>`
            for more information.
        r  zJ.pixel_array_options() got an unexpected keyword argument 'use_v2_backend'r  r  rB  Fru   N)
r   r~   rv   r   r   r[   r   r   r   r   )rG   r  r  rB  r  rr   rH   rH   rI   pixel_array_options  s   ^
zDataset.pixel_array_optionsc                 C   s    t  stdt j| |ddS )a9  Return an :class:`~numpy.ndarray` for the multiplex group at
        `index` in the (5400,0100) *Waveform Sequence*.

        .. versionadded:: 2.1

        Parameters
        ----------
        index : int
            The index of the multiplex group to return the array for.

        Returns
        ------
        numpy.ndarray
            The *Waveform Data* for the multiplex group as an
            :class:`~numpy.ndarray` with shape (samples, channels). If
            (003A,0210) *Channel Sensitivity* is present
            then the values will be in the units specified by the (003A,0211)
            *Channel Sensitivity Units Sequence*.

        See Also
        --------
        :func:`~pydicom.waveforms.numpy_handler.generate_multiplex`
        :func:`~pydicom.waveforms.numpy_handler.multiplex_array`
        z(The waveform data handler requires numpyF)as_raw)wave_handlerrT  rU  multiplex_array)rG   r  rH   rH   rI   waveform_array	  s   zDataset.waveform_arrayz)%(tag)s %(name)-35.35s %(VR)s: %(repval)selement_formatsequence_element_formatindent_formatc                 #   sR    d|   D ]  fddt D } jtjkr!|| V  q|| V  qdS )aT  Iterate through the :class:`Dataset` yielding formatted :class:`str`
        for each element.

        Parameters
        ----------
        element_format : str
            The string format to use for non-sequence elements. Formatting uses
            the attributes of
            :class:`~pydicom.dataelem.DataElement`. Default is
            ``"%(tag)s %(name)-35.35s %(VR)s: %(repval)s"``.
        sequence_element_format : str
            The string format to use for sequence elements. Formatting uses
            the attributes of
            :class:`~pydicom.dataelem.DataElement`. Default is
            ``"%(tag)s %(name)-35.35s %(VR)s: %(repval)s"``
        indent_format : str or None
            Placeholder for future functionality.

        Yields
        ------
        str
            A string representation of an element.
        )	from_jsonto_jsonto_json_dictr9  descriptionvalidatec                    sD   i | ]}| d s |vr|tt |rt | nt |qS )_)
startswithcallabler   )ri   attrr
  	exclusionrH   rI   r   O	  s    z+Dataset.formatted_lines.<locals>.<dictcomp>N)iterallr   r6   r   r   )rG   r  r  r  	elem_dictrH   r  rI   formatted_lines%	  s   	zDataset.formatted_linesr   indenttop_level_onlyc                 C   sR  g }| j | }| j |d  }t| drL| jrLtjjrL|dd | jD ] }t|j ||t	|  W d   n1 s?w   Y  q$|dd | D ]U}t|jF |j
tjkr|| |j d|j dt|j d |s|jD ]}|||d  ||d	  qvn	||t	|  W d   n1 sw   Y  qNd
|S )a  Return a string of the DataElements in the Dataset, with indented
        levels.

        This private method is called by the ``__str__()`` method for handling
        print statements or ``str(dataset)``, and the ``__repr__()`` method.
        It is also used by ``top()``, therefore the `top_level_only` flag.
        This function recurses, with increasing indentation levels.

        ..versionchanged:: 2.0

            The file meta information is returned in its own section,
            if :data:`~pydicom.config.show_file_meta` is ``True`` (default)

        Parameters
        ----------
        indent : int, optional
            The indent level offset (default ``0``).
        top_level_only : bool, optional
            When True, only create a string for the top level elements, i.e.
            exclude elements within any Sequences (default ``False``).

        Returns
        -------
        str
            A string representation of the Dataset.
        rB   rP  zDataset.file_meta z-<49Nrt   z  z item(s) ---- z	---------
)indent_charsrC  rP  r   r   show_file_metard  r1   rU   reprr6   r   r   r   rl   rS   _pretty_strrf  )rG   r  r  strings
indent_strnextindent_strr
  r>   rH   rH   rI   r  ]	  sD   



zDataset._pretty_strc                 C   r   )a  Get the VR method used by the original encoding of the dataset.

        .. deprecated:: 3.0

            ``read_implicit_vr`` will be removed in v4.0, , use
            :attr:`~pydicom.dataset.Dataset.original_encoding` instead.

        Returns
        -------
        bool | None
            Returns ``None`` if the dataset has been created from scratch,
            otherwise returns ``True`` if the dataset was decoded from file
            or buffer and used implicit VR, ``False`` if it used explicit VR.
        r   z,' object has no attribute 'read_implicit_vr'z1.read_implicit_vr' will be removed in v4.0, use 'z.original_encoding[0]' instead)r   r[   r   r~   r   r'   r   r|   r   rH   rH   rI   read_implicit_vr	  s   
zDataset.read_implicit_vrc                 C   r   )a  Get the endianness used by the original encoding of the dataset.

        .. deprecated:: 3.0

            ``read_little_endian`` will be removed in v4.0, use
            :attr:`~pydicom.dataset.Dataset.original_encoding` instead.

        Returns
        -------
        bool | None
            Returns ``None`` if the dataset has been created from scratch,
            otherwise returns ``True`` if the dataset was decoded from file
            or buffer and used little endian encoding, ``False`` for big
            endian.
        r   z.' object has no attribute 'read_little_endian'z3.read_little_endian' will be removed in v4.0, use 'z.original_encoding[1]' instead)r   r[   r   r~   r   r'   r   r{   r   rH   rH   rI   read_little_endian	  s   

zDataset.read_little_endianc                 C   s$   dddt ddfdd}| | dS )z6Remove all private elements from the :class:`Dataset`.r>   r?   r
  rA   Nc                 S   s   |j jr
| |j = dS dS )z4Internal method to use as callback to walk() method.N)rU   r<  )r>   r
  rH   rH   rI   remove_callback	  s   z4Dataset.remove_private_tags.<locals>.remove_callback)r    r   )rG   r  rH   rH   rI   remove_private_tags	  s   zDataset.remove_private_tagsimplicit_vrlittle_endianenforce_file_format	overwrite_Dataset__write_like_originalr  r  r  r  r  c            	   K   s   |dur
|du r
d}| j d durSt| di }|dd}	d}
z|	j}
W n ttfy<   |dur4|}
ntjs:| j}
Y nw |
durS| j d |
krStdt| j	 dt
j|| |f||||d| dS )	a  Encode the current :class:`Dataset` and write it to `filename`.

        See the documentation for :func:`~pydicom.filewriter.dcmwrite` for
        more detailed information.

        .. warning::

            Encoding a dataset with ``little_endian=False`` (i.e. as big
            endian) is not recommended. Big endian encoding was retired from
            the DICOM Standard in 2006.

        .. warning::

            This function cannot be used to convert a decoded dataset to an
            encoding that uses a different endianness, such as from big to
            little endian. :func:`~pydicom.filewriter.dcmwrite()` must be used
            instead, however the process is not automatic. See the
            documentation of :func:`~pydicom.filewriter.dcmwrite()` for
            details.

        .. versionchanged:: 3.0

            Added `implicit_vr`, `little_endian`, `enforce_file_format` and `overwrite`
            keyword arguments

        .. deprecated:: 3.0

            `write_like_original` will be removed in v4.0, please use
            `enforce_file_format` instead

        Parameters
        ----------
        filename : str | PathLike | BinaryIO
            The path, file-like or writeable buffer to write the encoded
            dataset to. If using a buffer it must have ``write()``, ``seek()``
            and ``tell()`` methods.
        write_like_original : bool, optional
            If ``True`` (default) then write the dataset as-is, otherwise
            ensure that the dataset is written in the DICOM File Format or
            raise an exception is that isn't possible. This parameter is
            deprecated, please use `enforce_file_format` instead.
        implicit_vr : bool, optional
            Required if the dataset has no valid public *Transfer Syntax UID*
            set in the file meta and
            :attr:`~pydicom.dataset.Dataset.is_implicit_VR` or
            :attr:`~pydicom.dataset.Dataset.original_encoding` are ``None``. If
            ``True`` then encode using implicit VR, otherwise use explicit VR.
        little_endian : bool, optional
            Required if the dataset has no valid public *Transfer Syntax UID*
            set in the file meta and
            :attr:`~pydicom.dataset.Dataset.is_little_endian` or
            :attr:`~pydicom.dataset.Dataset.original_encoding` are ``None``. If
            ``True`` (default) then use little endian byte order when encoding,
            otherwise use big endian (not recommended).
        enforce_file_format : bool, optional
            If ``True`` then ensure the dataset is written in the DICOM File
            Format or raise an exception if that isn't possible. If ``False``
            (default) then write the dataset as-is, preserving the following -
            which may result in a non-conformant file:

            - ``Dataset.preamble``: if the dataset has no preamble then none
              will be written
            - ``Dataset.file_meta``: if the dataset is missing any required
              *File Meta Information Group* elements then they will not be
              added or written
        overwrite : bool, optional
            If ``False`` and `filename` is a :class:`str` or PathLike, then raise a
            :class:`FileExistsError` if a file already exists with the given filename
            (default ``True``).

        See Also
        --------
        pydicom.filewriter.dcmwrite
            Encode a :class:`Dataset` and write it to a file or buffer.
        NTrB   rP  rQ  r   z.save_as()' cannot be used to convert between little and big endian encoding. Please read the documentation for filewriter.dcmwrite() if this is what you really want to dor  )r   r   rv   r"  r   rM   r   r~   r   r[   r   dcmwrite)rG   r  r  r  r  r  r  rr   rP  syntax
use_littlerH   rH   rI   save_as	  s>   Z

zDataset.save_asc                 C   s   t | dst | _dS dS )z5Create an empty ``Dataset.file_meta`` if none exists.rP  N)rC  FileMetaDatasetrP  r   rH   rH   rI   ensure_file_meta]
  s   
zDataset.ensure_file_metac                 C   s   | ds	| r|dkr| | dS t| || dS t|}|durA|| vr4t|}t|||}n| | }||_|| |< dS t	|rMt
d| dt|rkd| d}tjdkrbt| n	tjd	krkt
|t| || dS )
a.  Intercept any attempts to set a value for an instance attribute.

        If name is a DICOM keyword, set the corresponding tag and DataElement.
        Else, set an instance (python) attribute as any other class would do.

        Parameters
        ----------
        name : str
            The keyword for the element you wish to add/change. If
            `name` is not a DICOM element keyword then this will be the
            name of the attribute to be added/changed.
        value
            The value for the attribute to be added/changed.
        is_rP  Nr   z\' is a DICOM repeating group element and must be added using the add() or add_new() methods.zCamel case attribute 'z:' used which is not in the element keyword data dictionaryr   r   )r  islower_set_file_metarc   __setattr__r   r   r    rS   r   rM   _RE_CAMEL_CASEr   r   INVALID_KEYWORD_BEHAVIORr'   )rG   r   rS   rU   r   r
  r   rH   rH   rI   r  c
  s4   






zDataset.__setattr__Dataset | Nonec                 C   sX   |du r|| j d< dS t|ts| jj}td| dt|ts%t|}|| j d< dS )z2Set the Dataset's File Meta Information attribute.NrP  r   z0.file_meta' must be a 'FileMetaDataset' instance)r   ry   r?   rW   r[   r   r  )rG   rS   cls_namerH   rH   rI   r  
  s   



zDataset._set_file_metar
  c              
   C   sj  t |tr	tdzt|}W n ty$ } z	td| d|d}~ww t |ttB s0tdt |j	t
r:|j	}nt|j	}||krNtd| d| d|jrtd	|  |jd
? }t|j|}|| v r||krt |tryt|| j| d}| | j|_|tv rd| _i | _|| j|< |jtjkrt |trt |jtjst|j|_| tt| dS dS dS )a3  Operator for ``Dataset[key] = elem``.

        Parameters
        ----------
        key : int or Tuple[int, int] or str
            The tag for the element to be added to the :class:`Dataset`.
        elem : dataelem.DataElement or dataelem.RawDataElement
            The element to add to the :class:`Dataset`.

        Raises
        ------
        NotImplementedError
            If `key` is a :class:`slice`.
        ValueError
            If the `key` value doesn't match the corresponding
            :attr:`DataElement.tag<pydicom.dataelem.tag>`.
        z3Slicing is not supported when setting Dataset itemszUnable to convert the key 'z' to an element tagNz-Dataset items must be 'DataElement' instancesz	The key 'z'' doesn't match the 'DataElement' tag 'r   zSetting private tag rC   r   )ry   r   rS  r/   r   rM   r    r"   r   rU   r0   r<  r   rg  r  rD   r!   r   rS   rE   r   r   r   rx   r6   r   r   r   Sequencer  r   )rG   r=   r
  r   elem_tagr   private_creator_tagrH   rH   rI   __setitem__
  sT   





zDataset.__setitem__rt  photometric_interpretationbits_storedc                C   s   t | ||||d dS )a  Use an :class:`~numpy.ndarray` to set the *Pixel Data* and related
        Image Pixel module elements.

        .. versionadded:: 3.0

        The following :dcm:`Image Pixel<part03/sect_C.7.6.3.3.html#table_C.7-11c>`
        module elements values will be added, updated or removed as necessary:

        * (0028,0002) *Samples per Pixel* using a value corresponding to
          `photometric_interpretation`.
        * (0028,0104) *Photometric Interpretation* from `photometric_interpretation`.
        * (0028,0006) *Planar Configuration* will be added and set to ``0`` if
          *Samples per Pixel* is > 1, otherwise it will be removed.
        * (0028,0008) *Number of Frames* from the array :attr:`~numpy.ndarray.shape`,
          however it will be removed if `arr` only contains a single frame.
        * (0028,0010) *Rows* and (0028,0011) *Columns* from the array
          :attr:`~numpy.ndarray.shape`.
        * (0028,0100) *Bits Allocated* from the array :class:`~numpy.dtype`.
        * (0028,0101) *Bits Stored* and (0028,0102) *High Bit* from `bits_stored`.
        * (0028,0103) *Pixel Representation* from the array :class:`~numpy.dtype`.

        In addition:

        * The *Transfer Syntax UID* will be set to *Explicit VR Little Endian* if
          it doesn't already exist or uses a compressed (encapsulated) transfer syntax.
        * If `generate_instance_uid` is ``True`` (default) then the *SOP Instance UID*
          will be added or updated.

        Parameters
        ----------
        arr : numpy.ndarray
            An array with :class:`~numpy.dtype` uint8, uint16, int8 or int16. The
            array must be shaped as one of the following:

            * (rows, columns) for a single frame of grayscale data.
            * (frames, rows, columns) for multi-frame grayscale data.
            * (rows, columns, samples) for a single frame of multi-sample data
              such as RGB.
            * (frames, rows, columns, samples) for multi-frame, multi-sample data.
        photometric_interpretation : str
            The value to use for (0028,0004) *Photometric Interpretation*. Valid
            values are ``"MONOCHROME1"``, ``"MONOCHROME2"``, ``"PALETTE COLOR"``,
            ``"RGB"``, ``"YBR_FULL"``, ``"YBR_FULL_422"``.
        bits_stored : int
            The value to use for (0028,0101) *Bits Stored*. Must be no greater than
            the number of bits used by the :attr:`~numpy.dtype.itemsize` of `arr`.
        generate_instance_uid : bool, optional
            If ``True`` (default) then add or update the (0008,0018) *SOP Instance
            UID* element with a value generated using :func:`~pydicom.uid.generate_uid`.

        Raises
        ------
        NotImplementedError
            If the dataset has a big-endian *Transfer Syntax UID*.
        r  N)r.   )rG   rs  r  r  rt  rH   rH   rI   r.   
  s   ?
zDataset.set_pixel_datac                 C   s   d}t | jv r| t  j}nt| dr| j}|dur't|tr$td|v n|| _|jt	j
kr/dS |jD ]3}t |jv r\|jt  j}|durRt|trNtd|v n||_q2t| dr[| j|_q2t| dre| j|_q2dS )zqSet the `_pixel_rep` attribute for the current dataset and child
        datasets of the sequence element `elem`.N
_pixel_rep   )r3   rx   rS   rC  r  ry   bytesr`   r6   r   r   )rG   r
  pritemrH   rH   rI   r  ?  s,   





z!Dataset._set_pixel_representationr   zTagType | Noner   r   c                    s   |durt |} durt   t| j }|sg S |du rH du r0|dkr)|S |dd| S tt fdd|}|dkrA|S |dd| S t||} du rX||d| S t| }|||| S )a  Return the element tags in the Dataset that match the slice.

        Parameters
        ----------
        start : int or 2-tuple of int or None
            The slice's starting element tag value, in any format accepted by
            :func:`~pydicom.tag.Tag`.
        stop : int or 2-tuple of int or None
            The slice's stopping element tag value, in any format accepted by
            :func:`~pydicom.tag.Tag`.
        step : int or None
            The slice's step size.

        Returns
        ------
        list of BaseTag
            The tags in the :class:`Dataset` that meet the conditions of the
            slice.
        NrB   c                    s   |  k S rg   rH   )r   r   rH   rI   <lambda>  s    z(Dataset._slice_dataset.<locals>.<lambda>)r/   r   rx   rn   listr   r   )rG   r   r   r   all_tags
step1_listi_starti_stoprH   r  rI   r   _  s"   

zDataset._slice_datasetc                 C   s   |   S )zHandle str(dataset).

        ..versionchanged:: 2.0

            The file meta information was added in its own section,
            if :data:`pydicom.config.show_file_meta` is ``True``

        r  r   rH   rH   rI   __str__  s   	zDataset.__str__c                 C   s   | j ddS )z?Return a :class:`str` representation of the top level elements.T)r  r  r   rH   rH   rI   top  r   zDataset.topc                 C   s   t | S )zReturn a :class:`list` of valid names for auto-completion code.

        Used in IPython, so that data element names can be found and offered
        for autocompletion on the IPython command line.
        )r   r   rH   rH   rI   trait_names  s   zDataset.trait_namesdc                 C   sD   t | D ]\}}t|trt| || q|| ttt|< qdS )zExtend :meth:`dict.update` to handle DICOM tags and keywords.

        Parameters
        ----------
        d : dict or Dataset
            The :class:`dict` or :class:`Dataset` to use when updating the
            current object.
        N)r  r   ry   ra   setattrr/   r   r`   )rG   r  r=   rS   rH   rH   rI   r     s
   	
zDataset.updatec                 c   s<    | D ]}|V  |j tjkr|jD ]	}| E dH  qqdS )a  Iterate through the :class:`Dataset`, yielding all the elements.

        Unlike ``iter(Dataset)``, this *does* recurse into sequences,
        and so yields all elements as if dataset were "flattened".

        Yields
        ------
        dataelem.DataElement
        N)r6   r   r   rS   r  )rG   r
  r   rH   rH   rI   r    s   

zDataset.iterallcallbackr   c              	   C   s   t | j }|D ]8}t|* | | }|| | |r2|| v r2|jtjkr2|j}|D ]}|| q*W d   n1 s<w   Y  q	dS )a"  Iterate through the :class:`Dataset's<Dataset>` elements and run
        `callback` on each.

        Visit all elements in the :class:`Dataset`, possibly recursing into
        sequences and their items. The `callback` function is called for each
        :class:`~pydicom.dataelem.DataElement` (including elements
        with a VR of 'SQ'). Can be used to perform an operation on certain
        types of elements.

        For example,
        :meth:`~Dataset.remove_private_tags` finds all elements with private
        tags and deletes them.

        The elements will be returned in order of increasing tag number within
        their current :class:`Dataset`.

        Parameters
        ----------
        callback
            A callable function that takes two arguments:

            * a :class:`Dataset`
            * a :class:`~pydicom.dataelem.DataElement` belonging
              to that :class:`Dataset`

        recursive : bool, optional
            Flag to indicate whether to recurse into sequences (default
            ``True``).
        N)	r   rx   rn   r1   r6   r   r   rS   r   )rG   r  r   r4  rU   r   sequencer>   rH   rH   rI   r     s    

zDataset.walkclsjson_datasetbulk_data_uri_handlerc              	   C   s   t |ttB tB rttttf t|}|  }|	 D ]8\}}|d }t
t| ttj@ }t|dkr=d}dg}	n|d }|| }	t| |||	||}
||
 q|S )a;  Return a :class:`Dataset` from a DICOM JSON Model object.

        See the DICOM Standard, Part 18, :dcm:`Annex F<part18/chapter_F.html>`.

        Parameters
        ----------
        json_dataset : dict, str, bytes or bytearray
            :class:`dict`, :class:`str`, :class:`bytes` or :class:`bytearray`
            representing a DICOM Data Set formatted based on the :dcm:`DICOM
            JSON Model<part18/chapter_F.html>`.
        bulk_data_uri_handler : callable, optional
            Callable function that accepts either the tag, vr and
            "BulkDataURI" value or just the "BulkDataURI" value of the JSON
            representation of a data element and returns the actual value of
            that data element (retrieved via DICOMweb WADO-RS). If no
            `bulk_data_uri_handler` is specified (default) then the
            corresponding element will have an "empty" value such as
            ``""``, ``b""`` or ``None`` depending on the `vr` (i.e. the
            Value Multiplicity will be 0).

        Returns
        -------
        Dataset
        r   r   Nrt   )ry   ra   r  	bytearrayr   dictr   jsonloadsr   r_   r   rn   r   JSON_VALUE_KEYSrl   r    r  r   )r  r  r  r>   rU   mappingr   unique_value_keys	value_keyrS   r   rH   rH   rI   r    s$   "zDataset.from_json   bulk_data_thresholdbulk_data_element_handlersuppress_invalid_tagsc           
      C   s   i }|rt  nt }|L |  D ]>}|d}z| | }|j||d||< W q tyP }	 z|s;td|  |	td| d|	  W Y d}	~	qd}	~	ww W d   |S 1 s\w   Y  |S )a  Return a dictionary representation of the :class:`Dataset`
        conforming to the DICOM JSON Model as described in the DICOM
        Standard, Part 18, :dcm:`Annex F<part18/chapter_F.html>`.

        Parameters
        ----------
        bulk_data_threshold : int, optional
            Threshold for the length of a base64-encoded binary data element
            above which the element should be considered bulk data and the
            value provided as a URI rather than included inline (default:
            ``1024``). Ignored if no bulk data handler is given.
        bulk_data_element_handler : callable, optional
            Callable function that accepts a bulk data element and returns a
            JSON representation of the data element (dictionary including the
            "vr" key and either the "InlineBinary" or the "BulkDataURI" key).
        suppress_invalid_tags : bool, optional
            Flag to specify if errors while serializing tags should be logged
            and the tag dropped or if the error should be bubbled up.

        Returns
        -------
        dict
            :class:`Dataset` representation based on the DICOM JSON Model.
        08X)r  r  zError while processing tag z: N)	r   strict_readingr	   rn   r  r   r   errorwarning)
rG   r  r  r  r  contextr=   json_keyr   r   rH   rH   rI   r  1  s.   "
zDataset.to_json_dictdump_handlerc                 C   s2   |du rdt dtfdd}|}|| j|||dS )a  Return a JSON representation of the :class:`Dataset`.

        See the DICOM Standard, Part 18, :dcm:`Annex F<part18/chapter_F.html>`.

        Parameters
        ----------
        bulk_data_threshold : int, optional
            Threshold for the length of a base64-encoded binary data element
            above which the element should be considered bulk data and the
            value provided as a URI rather than included inline (default:
            ``1024``). Ignored if no bulk data handler is given.
        bulk_data_element_handler : callable, optional
            Callable function that accepts a bulk data element and returns a
            JSON representation of the data element (dictionary including the
            "vr" key and either the "InlineBinary" or the "BulkDataURI" key).
        dump_handler : callable, optional
            Callable function that accepts a :class:`dict` and returns the
            serialized (dumped) JSON string (by default uses
            :func:`json.dumps`).

            .. note:

                Make sure to use a dump handler that sorts the keys (see
                example below) to create DICOM-conformant JSON.
        suppress_invalid_tags : bool, optional
            Flag to specify if errors while serializing tags should be logged
            and the tag dropped or if the error should be bubbled up.

        Returns
        -------
        str
            :class:`Dataset` serialized into a string based on the DICOM JSON
            Model.

        Examples
        --------
        >>> def my_json_dumps(data):
        ...     return json.dumps(data, indent=4, sort_keys=True)
        >>> ds.to_json(dump_handler=my_json_dumps)
        Nr  rA   c                 S   s   t j| ddS )NT)	sort_keys)r  dumps)r  rH   rH   rI   	json_dump  s   z"Dataset.to_json.<locals>.json_dump)r  )r   ra   r  )rG   r  r  r  r  r  rH   rH   rI   r  c  s   /zDataset.to_json)r   rS   c                C   s   |du r|du rt d|dur&zt|  W n ty%   t d| dw |dur:t|ts:tdt|j dt|}| 	|}|du rOtd| dt|t
s\td| d	|durb|n|j}|durk|n|j}|j||d
| j|< dS )a
  Modify the VR or value for the raw element with `tag`.

        When a :class:`Dataset` is created most of it's elements are in their
        :class:`~pydicom.dataelem.RawDataElement` form, and only upon trying to access
        the element is it converted to a :class:`~pydicom.dataelem.DataElement`.
        When this conversion fails due to non-conformance issues, this method can be
        used to modify the raw element data prior to conversion in order to fix any
        issues.

        Example
        -------

        Change the VR for the element with tag (0029,1026) before conversion to
        :class:`~pydicom.dataelem.DataElement`.

            >>> from pydicom import examples
            >>> ds = examples.ct
            >>> ds.update_raw_element(0x00291026, vr="US")
            >>> elem = ds[0x00291026]  # conversion to DataElement occurs here
            >>> type(elem)
            <class 'pydicom.dataelem.DataElement'>
            >>> elem.VR
            "US"

        Parameters
        ----------
        tag : int | str | tuple[int, int] | BaseTag
            The tag for a :class:`~pydicom.dataelem.RawDataElement` in the dataset.
        vr : str, optional
            Required if `value` is not used, the value to use for the modified
            element's VR, if not used then the existing VR will be kept.
        value : bytes, optional
            Required if `vr` is not used, the value to use for the modified element's
            raw encoded value, if not used then the existing value will be kept.
        Nz/Either or both of 'vr' and 'value' are requiredzInvalid VR value 'r   z'value' must be bytes, not 'zNo element with tag z
 was foundzThe element with tag z[ has already been converted to a 'DataElement' instance, this method must be called earlier)r6   rS   )rM   r   r   ry   r  r   r   r[   r/   r  r"   r6   rS   _replacerx   )rG   rU   r   rS   r  rH   rH   rI   update_raw_element  s*   &


zDataset.update_raw_element)rA   r?   rg   )rA   r   )rA   N)r=   r   rA   N)r=   r   rA   r   )F)rt   )Nrt   F)r   F)rS   r  rA   NT)r  NF)r  NNF)yr[   r\   r]   r^   r  rp   r   rJ   r   r   BaseExceptionr   rb   r   r    r   r2   ra   rT   r`   r   r   r   rP   r   r   r   rR   r  r   r   r   r   rv   r_   r0   r   _DatasetValuer   rn   r   r   r   propertyr   r   r   r   setterr   rQ   r<   r   r  r  r  r  r#  r"  r.  r   r!  r2  r   r5  r"   r6  r7  r8  r9  r:  r;  r@  rH  rD  rE  rV  floatr(   r*   r  r+   r  r  default_element_formatdefault_sequence_element_formatr  r  r  r  r  osPathLiker   r   r$   r  r  r  r  r  r.   r  r   r  r  r  r   r  r   r   classmethodr  r  r  r  r  r  r  __repr____classcell__rH   rH   r   rI   r?      s    2



-*-?# 
+d
I!
%
/ 
!%	CV%F
	


 
^A
n 
8:	

~<M
G 
5
, <

4
?A_FileDatasetFileDataset)boundc                   @   sf   e Zd ZdZ				ddeeB eB dededB ddd	e	d
e	ddfddZ
deeef dd fddZdS )r   a  An extension of :class:`Dataset` to make reading and writing to
    file-like easier.

    .. versionchanged:: 3.0

        Added the `buffer` attribute and the `filename` attribute has been changed to
        only contain the filename the dataset was read from (if any).

    Attributes
    ----------
    preamble : str | bytes | None
        The optional DICOM preamble prepended to the :class:`FileDataset`, if
        available.
    file_meta : FileMetaDataset | None
        The Dataset's file meta information as a :class:`FileMetaDataset`, if
        available (``None`` if not present). Consists of group ``0x0002`` elements.
    filename : str | None
        The filename associated with the :class:`FileDataset` if read from
        a file or file-like, or ``None`` if the dataset has been read from a
        buffer-like object.
    buffer : ReadableBuffer | None
        The buffer-like object the :class:`FileDataset` was read from, or
        ``None`` if the dataset has been read from a file or file-like.
    fileobj_type
        The type of object the :class:`FileDataset` was read from.
    timestamp : float | None
        The modification time of the file the :class:`FileDataset` was read
        from, ``None`` if the modification time is not available.
    NTfilename_or_objr>   preamblerP  zFileMetaDataset | Noner#  r"  rA   c                 C   s  t | | || _|dur|nt | _tjs|| _|| _|| _	|| _
d| _d| _d| _t|}t|tr;|| _t| _n+t|tjrI|j| _t| _n|| _t|| _t|ddr\|j| _n
t|ddrf|j| _d| _| jr}tj| jrt| jj| _dS dS dS )a  Initialize a :class:`FileDataset` read from a DICOM file.

        Parameters
        ----------
        filename_or_obj : str, PathLike, file-like or readable buffer

            * :class:`str` or path: the full path to the dataset file
            * file-like: a file-like object in "rb" mode
            * readable buffer: an object with ``read()``, ``tell()`` and
              ``seek()`` methods such as :class:`io.BytesIO`.
        dataset : Dataset or dict
            Some form of dictionary, usually a :class:`Dataset` returned from
            :func:`~pydicom.filereader.dcmread`.
        preamble : bytes or str, optional
            The 128-byte DICOM preamble.
        file_meta : FileMetaDataset, optional
            The file meta :class:`FileMetaDataset`, such as the one returned by
            :func:`~pydicom.filereader.read_file_meta_info`, or an empty
            :class:`FileMetaDataset` if no file meta information is in the
            file.
        is_implicit_VR : bool, optional
            ``True`` (default) if implicit VR transfer syntax used; ``False``
            if explicit VR.
        is_little_endian : bool
            ``True`` (default) if little-endian transfer syntax used; ``False``
            if big-endian.
        Nr   r  )r?   rJ   r  r  rP  r   r~   r   r   r|   r{   r  r  r  r%   ry   ra   openioBufferedReaderr   r   r   r  r  pathexistsstatst_mtime)rG   r  r>   r  rP  r#  r"  rH   rH   rI   rJ     s:   $


zFileDataset.__init__rV   c                 C   s   | j }||}||t| < | j D ]I\}}|dkrRzt||t|| W q tyQ } zt	dt
|j d| d t||td| W Y d}~qd}~ww t||t|| q|S )zReturn a deep copy of the file dataset.

        Sets the `buffer` to ``None`` if it's been closed or is otherwise not copyable.

        Returns
        -------
        FileDataset
            A deep copy of the file dataset.
        r  zThe z exception 'z' occurred trying to deepcopy the buffer-like the dataset was read from, the 'buffer' attribute will be set to 'None' in the copied objectN)rW   __new__rX   r   r   r  r   deepcopyr   r'   r   r[   )rG   rV   r  resultkvr   rH   rH   rI   rZ   S  s    

 	zFileDataset.__deepcopy__)NNTT)r[   r\   r]   r^   r&   r   r#   rp   r  rb   rJ   r  r`   r   rZ   rH   rH   rH   rI   r     s,    "

LTrP  r  enforce_standardc                    s      D ]}|jjdkrtdq|rOd vs d jrd _d vs( d jr-tt _d vr:dd	t
  _ fd	d
dD }|rQtdd	| dS dS )a  Validate the *File Meta Information* elements in `file_meta`.

    Parameters
    ----------
    file_meta : Dataset
        The *File Meta Information* data elements.
    enforce_standard : bool, optional
        If ``False``, then only a check for invalid elements is performed.
        If ``True`` (default), the following elements will be added if not
        already present and the Type 1 elements given a value if empty:

        * (0002,0001) *File Meta Information Version*, Type 1
        * (0002,0012) *Implementation Class UID*, Type 1
        * (0002,0013) *Implementation Version Name*, Type 3

        and the following elements will be checked to ensure they're present
        and have a non-empty value:

        * (0002,0002) *Media Storage SOP Class UID*, Type 1
        * (0002,0003) *Media Storage SOP Instance UID*, Type 1
        * (0002,0010) *Transfer Syntax UID*, Type 1

    Raises
    ------
    ValueError
        If `enforce_standard` is ``True`` and any of the Type 1 *File Meta
        Information* elements are missing from `file_meta` or have no value.
    ValueError
        If any non-Group 2 Elements are present in `file_meta`.
    r  zTOnly File Meta Information group (0002,eeee) elements may be present in 'file_meta'.FileMetaInformationVersions    ImplementationClassUIDImplementationVersionNamezPYDICOM .c                    s4   g | ]}| vs | j rt| d t| qS ) )is_emptyr/   r   r   rP  rH   rI   r     s
    z&validate_file_meta.<locals>.<listcomp>)i  i  i  zSRequired File Meta Information elements are either missing or have an empty value: r_  N)r6  rU   rD   rM   r  r  r5   r4   r  rf  r   r  r   )rP  r  r
  invalidrH   r  rI   validate_file_metar  s:   "

r  c                       s   e Zd ZdZdededdf fddZededdfd	d
Zddde	ddf fddZ
edeeef ed B fddZ  ZS )r  zContains a collection (dictionary) of group 2 DICOM Data Elements.

    .. versionadded:: 2.0

    Derived from :class:`~pydicom.dataset.Dataset`, but only allows
    Group 2 (File Meta Information) data elements
    rq   rr   rA   Nc                    sZ   t  j|i | t| j |  |  |  |  |  |  |  |  |  |  |  |  |  |  dS )ar  Initialize a FileMetaDataset

        Parameters are as per :class:`Dataset`; this overrides the super class
        only to check that all are group 2 data elements

        Raises
        ------
        ValueError
            If any data elements are not group 2.
        TypeError
            If the passed argument is not a :class:`dict` or :class:`Dataset`
        N)r   rJ   r  r  rx   r   r   rH   rI   rJ     s    zFileMetaDataset.__init__
init_valuec                 C   sZ   | du rdS t | ttB stdt|  dd |  D }|r+tdd| dS )a  Raise errors if initialization value is not acceptable for file_meta

        Parameters
        ----------
        init_value: dict or Dataset
            The tag:data element pairs to initialize a file meta dataset

        Raises
        ------
        TypeError
            If the passed argument is not a :class:`dict` or :class:`Dataset`
        ValueError
            If any data elements passed are not group 2.
        Nz(Argument must be a dict or Dataset, not c                 S   s&   g | ]}t |jd krtt |qS )r  )r/   rD   ra   r   rH   rH   rI   r     s   & z,FileMetaDataset.validate.<locals>.<listcomp>z]File meta datasets may only contain group 2 elements but the following elements are present: r_  )ry   r?   r  r   r   rn   rM   rf  )r  
non_group2rH   rH   rI   r    s   zFileMetaDataset.validater=   r   rS   c                    sB   t |jtr
|j}nt|j}|jdkrtdt || dS )a  Override parent class to only allow setting of group 2 elements.

        Parameters
        ----------
        key : int or Tuple[int, int] or str
            The tag for the element to be added to the Dataset.
        value : dataelem.DataElement or dataelem.RawDataElement
            The element to add to the :class:`FileMetaDataset`.

        Raises
        ------
        ValueError
            If `key` is not a DICOM Group 2 tag.
        r  z;Only group 2 data elements are allowed in a FileMetaDatasetN)ry   rU   r0   r/   rD   rM   r   r  )rG   r=   rS   rU   r   rH   rI   r    s   

zFileMetaDataset.__setitem__r/  c                 C   s,   |  dd}|r|js|jsdS |j|jfS )a"  Return the transfer syntax encoding method (if any)

        Returns
        -------
        tuple[bool, bool] | tuple[None, None]
            If the file meta has a valid public Transfer Syntax UID then
            returns (is implicit, is little), otherwise returns (None, None).
        rQ  Nr/  )rv   r<  is_transfer_syntaxr#  r"  )rG   rX  rH   rH   rI   _tsyntax_encoding  s   
z!FileMetaDataset._tsyntax_encoding)r[   r\   r]   r^   rp   r   rJ   staticmethodr  r  r  r  r_   rb   r  r  rH   rH   r   rI   r    s     (za(?P<start>(^[A-Za-z])((?=.+?[A-Z])[A-Za-z0-9]+)|(^[A-Z])([A-Za-z0-9]+))(?P<last>[A-Za-z0-9][^_]$)rg   r  )ir^   r   r  r  r  os.pathrebisectr   collections.abcr   r   r   r   r   r   
contextlibr	   importlib.utilr
   r\  	itertoolsr   typesr   typingr   r   r   r   r   r   r   r   r~  r   r   r   pydicom._versionr   pydicom.charsetr   r   pydicom.configr   pydicom.datadictr   r   r   r   r   r   pydicom.dataelemr    r!   r"   pydicom.filebaser#   r$   pydicom.fileutilr%   r&   pydicom.miscr'   pydicom.pixelsr(   r)   r*   r+   pydicom.pixels.utilsr,   r-   r.   pydicom.tagr/   r0   r1   r2   r3   pydicom.uidr4   r5   pydicom.valuerepr6   r   r7   pydicom.waveformsr8   r  r   r<   r  ra   rb   ro   r  rp   __annotations__r?   r  r   r  r  compiler  rH   rH   rH   rI   <module>   s    $
  $                         
Hu