o
    i                     @   s  d Z ddl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mZmZ ddlmZ ddlZdd	lmZ dd
lmZmZmZ ddlmZmZmZ ddlmZmZmZ ddlm Z m!Z!m"Z"m#Z# ddl$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/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z: ddl;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZE ddlFmGZG ejHrddlIZIh dZJh dZKdd eLdddD ZMdedeNe deOdefd d!ZP	dwdeeB d"edeOdeNe dB deeB f
d#d$ZQ	dwd"edeOdeNe dB defd%d&ZRd'e"ded(eSddfd)d*ZTd'e"deddfd+d,ZUd'e"deddfd-d.ZVd'e"deddfd/d0ZWd1edeOfd2d3ZXd1eSeeS B deSfd4d5ZY	dwd'e"ded6eNeS dB ddfd7d8ZZdxd'e"ded:eSddfd;d<Z[	dwd'e"ded6eNeS dB ddfd=d>Z\d'e"deddfd?d@Z]d1e?dB deSfdAdBZ^d'e"deddfdCdDZ_d1e@dB deSfdEdFZ`d'e"deddfdGdHZad1eAdB deSfdIdJZbd'e"deddfdKdLZc	dwd'e"deeB d6eSeNeS B dB ddfdMdNZdeeeOdB eOdB f Zfefd'e"dOedPeSeNeS B degfdQdRZhd'e"ded6eNeS ddfdSdTZid'e"dOed6eNeS ddfdUdVZjd'e"deddfdWdXZkd'e"deddfdYdZZl	[dyd'e"d\ed]eOddfd^d_Zmd"ed`e8dB daeOdB dbeOdB dceOdeeeOeOf fdddeZn	dwdddfdfd[dgdheOdB die&eB e#B dOedaeOdB dbeOdB djeOdceOdkeOdleddfdmdnZoi eCjpe[dfeCjqe[dfeCjreldfeCjse[dfeCj?e_dfeCjte]dfeCj@eadfeCjueTdofeCjveTdpfeCj=e]dfeCjwe\dfeCjxe\dfeCjyeUdfeCjzeVdfeCj{eVdfeCj|eVdfeCj}eVdfi eCj~eVdfeCjeZdfeCje\dfeCjeTdqfeCjeidfeCjeTdrfeCje\dfeCjeTdsfeCjAecdfeCje\dfeCjeWdfeCjeTdtfeCjekdfeCje[dfeCjeTdufeCje\dfeCjeTdvfeCjeVdfeCjeVdfeCjeVdfeCjeUdfiZdS )zz(Functions related to writing DICOM data.    )SequenceMutableSequenceIterable)deepcopy)BufferedIOBase)pack)BinaryIOAnycast)CallableN)config)default_encodingconvert_encodingsencode_string)convert_raw_data_elementDataElementRawDataElement)Datasetvalidate_file_metaFileMetaDataset)	DicomFileDicomBytesIODicomIOWriteableBuffer)path_from_pathlikePathTypebuffer_remainingread_bufferreset_buffer_position)warn_and_log)
MultiValue)TagBaseTagItemTagItemDelimiterTagSequenceDelimiterTagtag_in_exception_LUT_DESCRIPTOR_TAGS)DeflatedExplicitVRLittleEndianUIDImplicitVRLittleEndianExplicitVRBigEndian)

PersonNameISDSclassDADTTMEXPLICIT_VR_LENGTH_32VRAMBIGUOUS_VRCUSTOMIZABLE_CHARSET_VR)convert_numbers>   ( ( 0( ( ( 0` ( ( 0` ( ( 	( (  ( @ @  ( !( R" >   
 T T T Tc                 C   s   h | ]}|d > dB qS )   i 0   .0xrP   rP   H/mnt/sdb/aimis/docanh/lib/python3.10/site-packages/pydicom/filewriter.py	<setcomp>i       rU   i `  i`     elem	ancestorsis_little_endianreturnc                 C   s&  |d }| j dkr.| jrtj| _| S |jd rtj| _| S tt|jdkr(tjntj| _| S | j t	v rt
dd |D d}|du rKt
dd |D d}|du r`d}d	|vrYd
|vs^|jdkr`d}|dkrgtjntj| _|dkrqdnd}| jdkrz| S | jdkr| jn	ttt | jd }t|tsttt| j||| _| S | j tv r|jd rtj| _| S tt|jdkrtjntj| _| S | j dkrttt |jd dkrtj| _| jdkr| S | jdkr| jn	ttt | jd }t|tsttt| j|d| _| S tj| _| S | j tv rtj| _| S )zoImplementation for `correct_ambiguous_vr_element`.
    See `correct_ambiguous_vr_element` for description.
    r       c                 s   s,    | ]}t |d ddurtt|jV  qdS )PixelRepresentationN)getattrr
   intr^   rQ   rP   rP   rT   	<genexpr>   s    
z0_correct_ambiguous_vr_element.<locals>.<genexpr>Nc                 s   s     | ]}t |d r|jV  qdS )
_pixel_repN)hasattrrb   rQ   rP   rP   rT   ra      s       r^   	PixelDataHhi0( )tagis_undefined_lengthr3   OBoriginal_encodingOWr
   r`   BitsAllocated_AMBIGUOUS_US_SS_TAGSnextr^   USSSVMvaluer   r	   
isinstancer6   bytes_AMBIGUOUS_OB_OW_TAGSWaveformBitsAllocatedLUTDescriptor_OVERLAY_DATA_TAGS)rX   rY   rZ   ds	pixel_rep	byte_type
elem_valuerP   rP   rT   _correct_ambiguous_vr_elementl   sz   	
e
aX
	

$
(


"
r~   rz   c              
   C   s   |du r|gn|}| j tv rAt| tr t| |d} || j|  z	t| || W | S  ty@ } ztd| j d| d}~ww | S )a  Attempt to correct the ambiguous VR element `elem`.

    When it's not possible to correct the VR, the element will be returned
    unchanged. Currently the only ambiguous VR elements not corrected for are
    all retired or part of DICONDE.

    If the VR is corrected and is 'US' or 'SS' then the value will be updated
    using the :func:`~pydicom.values.convert_numbers` function.

    .. versionchanged:: 3.0

        The `ancestors` keyword argument was added.

    Parameters
    ----------
    elem : dataelem.DataElement or dataelem.RawDataElement
        The element with an ambiguous VR.
    ds : dataset.Dataset
        The dataset containing `elem`.
    is_little_endian : bool
        The byte ordering of the values in the dataset.
    ancestors : list[pydicom.dataset.Dataset] | None
        A list of the ancestor datasets to look through when trying to find
        the relevant element value to use in VR correction. Should be ordered
        from closest to furthest. If ``None`` then will build itself
        automatically starting at `ds` (default).

    Returns
    -------
    dataelem.DataElement or dataelem.RawDataElement
        The corrected element
    N)rz   z'Failed to resolve ambiguous VR for tag z: )	r3   r4   rt   r   r   __setitem__rh   r~   AttributeError)rX   rz   rZ   rY   erP   rP   rT   correct_ambiguous_vr_element   s   &

r   c                 C   s   |du r| gn|}|   D ]1}|jtjkr2| |j }ttd |jD ]}|d| t||| q"q|jt	v r>t
|| || q|d= | S )a  Iterate through `ds` correcting ambiguous VR elements (if possible).

    When it's not possible to correct the VR, the element will be returned
    unchanged. Currently the only ambiguous VR elements not corrected for are
    all retired or part of DICONDE.

    If the VR is corrected and is 'US' or 'SS' then the value will be updated
    using the :func:`~pydicom.values.convert_numbers` function.

    .. versionchanged:: 3.0

        The `ancestors` keyword argument was added.

    Parameters
    ----------
    ds : pydicom.dataset.Dataset
        The dataset containing ambiguous VR elements.
    is_little_endian : bool
        The byte ordering of the values in the dataset.
    ancestors : list[pydicom.dataset.Dataset] | None
        A list of the ancestor datasets to look through when trying to find
        the relevant element value to use in VR correction. Should be ordered
        from closest to furthest. If ``None`` then will build itself
        automatically starting at `ds` (default).

    Returns
    -------
    ds : dataset.Dataset
        The corrected dataset

    Raises
    ------
    AttributeError
        If a tag is missing in `ds` that is required to resolve the ambiguity.
    Nr   r   )elementsr3   SQrh   r
   r   rs   insertcorrect_ambiguous_vrr4   r   )rz   rZ   rY   rX   itemrP   rP   rT   r     s   *

r   fpstruct_formatc              
   C   s   |j }|du s|dkrdS d| j }|| }zMz|j W n ty/   | t|| Y W dS w |dkrN|jtv rN|rN| t| d|d  |dd }| t| t| | g|R   W dS  t	yx } z	t
| d| d}~ww )	aa  Write a "value" of type struct_format from the dicom file.

    "Value" can be more than one number.

    Parameters
    ----------
    fp : file-like
        The file-like to write the encoded data to.
    elem : dataelem.DataElement
        The element to encode.
    struct_format : str
        The character format as used by the struct module.
    N z><rg   rf   r   rd   z
for data_element:
)rs   rZ   appendr   writer   rh   r'   len	ExceptionOSError)r   rX   r   rs   
endianCharformat_stringexcrP   rP   rT   write_numbersY  s&   

,r   c                 C      |j r.d}tt|j}t| t|D ]	}|| |7 }qW d   n1 s(w   Y  n	| tt|j}|d rB| d dS dS )z2Write a data_element with VR of 'other byte' (OB).r   NrW       is_bufferedr
   r   rs   r   r   r   ru   r   rX   bytes_writtenbufferchunkrP   rP   rT   write_OBvalue  s   
r   c                 C   r   )zWrite a data_element with VR of 'other word' (OW).

    Note: This **does not currently do the byte swapping** for Endian state.
    r   NrW   r   r   r   rP   rP   rT   write_OWvalue  s   
r   c                 C   s   t | |d dS )z9Write a data_element with VR of 'unique identifier' (UI). N)write_stringr   rX   rP   rP   rT   write_UI  s   r   valc                 C   s(   t jrt| tjrdS t| ttB tB S )z0Return True if `val` is a multi-value container.T)r   
have_numpyrt   numpyndarrayr    listtupler   rP   rP   rT   _is_multi_value  s   r   c                 C   s   t | r	d| S tt| S )z?Put a string together with delimiter if has more than one value\)r   joinr
   strr   rP   rP   rT   multi_string  s   

r   	encodingsc                    sr    st g |jdkrtt|jg}nttt |j}d fdd|D }t|d dkr2|d7 }| | d S )Nrd      \c                    s   g | ]}|  qS rP   )encode)rR   rX   r   rP   rT   
<listcomp>      zwrite_PN.<locals>.<listcomp>rW   r       )	r   rr   r
   r,   rs   r   r   r   r   )r   rX   r   r   encrP   r   rT   write_PN  s   
r    paddingc                 C   s^   t tttt B |j}|dur-t|d dkr||7 }t|tr&|t}| 	| dS dS )z+Write a single or multivalued ASCII string.NrW   r   )
r   r
   r   r   rs   r   rt   r   r   r   )r   rX   r   r   rP   rP   rT   r     s   

r   c                    s    pt g |j}|durlt|rHttt tt B |}t|d tr6ttt |}d fdd|D }n#ttt |}ddd |D }ntttB |}t|trYt	| }t
|d dkre|d }| | dS dS )	z*Write a single or multivalued text string.Nr   r   c                    s   g | ]}t | qS rP   )r   rR   r   r   rP   rT   r     r   zwrite_text.<locals>.<listcomp>c                 S   s   g | ]}|qS rP   rP   r   rP   rP   rT   r     s    rW   r   )r   rs   r   r
   r   ru   r   rt   r   r   r   r   )r   rX   r   r   rP   r   rT   
write_text  s"   


r   c                 C   s   |j }t|rttt tt B |}ddd |D }ntttB |}t|dr-|j}nt	|}t
|d dkr=|d }t|t}| | dS )	zAHandle IS or DS VR - write a number stored as a string of digits.r   c                 s   s(    | ]}t |d r|jnt|V  qdS )original_stringN)rc   r   r   rQ   rP   rP   rT   ra     s    
z&write_number_string.<locals>.<genexpr>r   rW   r   r   N)rs   r   r
   r   r-   r.   r   rc   r   r   r   ru   r   r   r   rX   r   rP   rP   rT   write_number_string  s   



r   c                 C   s&   | d u rdS t | dr| jS | dS )Nr   r   z%Y%m%d)rc   r   strftimer   rP   rP   rT   
_format_DA  s
   

r   c                 C      |j }t|trt| | d S t|r%ttt |}ddd |D }nt	tt|}t
|d dkr8|d }t|trB|t}| | d S )Nr   c                 s   &    | ]}t |tr|nt|V  qd S N)rt   r   r   rQ   rP   rP   rT   ra        $ zwrite_DA.<locals>.<genexpr>rW   r   r   )rs   rt   r   r   r   r
   r   r/   r   r   r   r   r   r   r   rP   rP   rT   write_DA     


r   c                 C   :   | d u rdS t | dr| jS | jdkr| dS | dS )Nr   r   r   z%Y%m%d%H%M%S.%f%zz%Y%m%d%H%M%S%zrc   r   microsecondr   r   rP   rP   rT   
_format_DT)     



r   c                 C   r   )Nr   c                 s   r   r   )rt   r   r   rQ   rP   rP   rT   ra   =  r   zwrite_DT.<locals>.<genexpr>rW   r   r   )rs   rt   r   r   r   r
   r   r0   r   r   r   r   r   r   r   rP   rP   rT   write_DT6  r   r   c                 C   r   )Nr   r   r   z	%H%M%S.%fz%H%M%Sr   r   rP   rP   rT   
_format_TMJ  r   r   c                 C   r   )Nr   c                 s   r   r   )rt   r   r   rQ   rP   rP   rT   ra   ^  r   zwrite_TM.<locals>.<genexpr>rW   r   r   )rs   rt   r   r   r   r
   r   r1   r   r   r   r   r   r   r   rP   rP   rT   write_TMW  r   r   c                 C   s  |  |j t }| j|_| j|_|j}| js-|r-t|dkr-d| d|jd}t||jrDt	t
|}|t	t|j |jdk}nMt	t|}|tvrUtd| d|pYtg}t|}tt	t| \}}|j}|js|tv sv|tjkr~||||d n|d	ur|||| n|js||| |r|jd
kr|jrt	t|j}	t|	 |	d}
W d	   n1 sw   Y  n
t	t|jd	d }
| jrdnd}|
|std|js| ntt	t|j}| js|tvr|s|dkrt d|j d| d tj!}| jst	t"|}| t|t |tv r| #d | js1|tvr1|s1| #| n
| $|r8dn| |jrE|| | n| |%  |r[|  t& | $d d	S d	S )zRWrite the data_element to file fp according to
    dicom media storage rules.
    rW   zCannot write ambiguous VR of 'z' for data element with tag zJ.
Set the correct VR before writing, or use an implicit VR transfer syntax    z2write_data_element: unknown Value Representation ''r   Nr\      s    s    zThe (7FE0,0010) 'Pixel Data' element value hasn't been encapsulated as required for a compressed transfer syntax - see pydicom.encaps.encapsulate() for more informationi  zThe value for the data element zy exceeds the size of 64 kByte and cannot be written in an explicit transfer syntax. The data element VR is changed from 'z#' to 'UN' to allow saving the data.r   )'	write_tagrh   r   rZ   is_implicit_VRr3   r   
ValueErroris_rawr
   r   r   ru   rs   lengthr   writersNotImplementedErrorr   r   ri   is_emptyr5   r   r   r   r   read
startswithtellr   r2   r   UNr   write_USwrite_ULgetvaluer%   )r   rX   r   r   vrmsgri   fnparamrs   pixel_data_bytesrh   value_lengthrP   rP   rT   write_data_elementk  s   	















r   datasetparent_encodingc           
   	   C   sN  t | ddt | ddf}d}tjs|j|jf}|j}d|v r*d|v r*d|v r*tdd|v r;d|vr5|}nd|vr;|}ttt	t	f |\| _| _|j
}||ksU|j|jkr^t|| j}|j}tdtB tt B |d|}|  }t| D ])}	|	jdkr|	jdkrqwt|	 t| ||	| W d   n1 sw   Y  qw|  | S )	a  Encode `dataset` and write the encoded data to `fp`.

    *Encoding*

    The `dataset` is encoded as specified by (in order of priority):

    * ``fp.is_implicit_VR`` and ``fp.is_little_endian``.
    * ``dataset.is_implicit_VR`` and ``dataset.is_little_endian``
    * If `dataset` has been decoded from a file or buffer then
      :attr:`~pydicom.dataset.Dataset.original_encoding`.

    Parameters
    ----------
    fp : pydicom.filebase.DicomIO
        The file-like to write the encoded dataset to.
    dataset : pydicom.dataset.Dataset
        The dataset to be encoded.
    parent_encoding : str | List[str], optional
        The character set to use for encoding strings, defaults to ``"iso8859"``.

    Returns
    -------
    int
        The number of bytes written to `fp`.
    _implicit_vrN_little_endianNNzF'fp.is_implicit_VR' and 'fp.is_little_endian' attributes are required SpecificCharacterSetr      )r_   r   _use_futurer   rZ   rk   r   r
   r   boolget_itemoriginal_character_set_character_setr   __getitem__r   r   getr   sortedkeyselementgroupr&   r   )
r   r   r   fp_encodingds_encodingor_encodingr   dataset_encodingfpStartrh   rP   rP   rT   write_dataset  sD   
 

r   c                 C   s&   t tt |jD ]}t| || qdS )aX  Write a sequence contained in `data_element` to the file-like `fp`.

    Parameters
    ----------
    fp : file-like
        The file-like to write the encoded data to.
    data_element : dataelem.DataElement
        The sequence element to write to `fp`.
    encodings : list of str
        The character encodings to use on text values.
    N)r
   r   r   rs   write_sequence_item)r   rX   r   rz   rP   rP   rT   write_sequence?  s   r   c                 C   s   |  t |  }| d t| ||d t|ddr'|  t | d dS |  }| | | || d  | | dS )a  Write a `dataset` in a sequence to the file-like `fp`.

    This is similar to writing a data_element, but with a specific tag for
    Sequence Item.

    See DICOM Standard, Part 5, :dcm:`Section 7.5<sect_7.5.html>`.

    Parameters
    ----------
    fp : file-like
        The file-like to write the encoded data to.
    dataset : Dataset
        The :class:`Dataset<pydicom.dataset.Dataset>` to write to `fp`.
    encodings : list of str
        The character encodings to use on text values.
    r   )r   !is_undefined_length_sequence_itemFr   r   N)r   r#   r   r   r   r_   r$   seek)r   r   r   length_locationlocationrP   rP   rT   r   Q  s   



r   c                 C   s   |  tt|j dS )z?Write a byte string for an DataElement of value 'UN' (unknown).N)r   r
   ru   rs   r   rP   rP   rT   write_UNq  s   r  c                 C   sz   zt ttt |j W n ty#   ttt|j}| | Y dS w dd ttt |jD }|D ]}| | q3dS )z#Write a data_element tag to a file.c                 S   s   g | ]}t |qS rP   )r!   )rR   rh   rP   rP   rT   r     s    z!write_ATvalue.<locals>.<listcomp>N)	iterr
   r   r	   rs   	TypeErrorr!   r`   r   )r   rX   rh   tagsrP   rP   rT   write_ATvaluev  s   r	  T	file_metaenforce_standardc                 C   sx   t || |rd|vrd|_t }d|_d|_t|| d|v r3| d |_|d t||d  | 	|
  dS )aJ
  Write the File Meta Information elements in `file_meta` to `fp`.

    If `enforce_standard` is ``True`` then the file-like `fp` should be
    positioned past the 128 byte preamble + 4 byte prefix (which should
    already have been written).

    **DICOM File Meta Information Group Elements**

    From the DICOM standard, Part 10,
    :dcm:`Section 7.1<part10/chapter_7.html#sect_7.1>`,  any DICOM file shall
    contain a 128-byte preamble, a 4-byte DICOM prefix 'DICM' and (at a
    minimum) the following Type 1 DICOM Elements (from
    :dcm:`Table 7.1-1<part10/chapter_7.html#table_7.1-1>`):

    * (0002,0000) *File Meta Information Group Length*, UL, 4
    * (0002,0001) *File Meta Information Version*, OB, 2
    * (0002,0002) *Media Storage SOP Class UID*, UI, N
    * (0002,0003) *Media Storage SOP Instance UID*, UI, N
    * (0002,0010) *Transfer Syntax UID*, UI, N
    * (0002,0012) *Implementation Class UID*, UI, N

    If `enforce_standard` is ``True`` then (0002,0000) will be added/updated,
    (0002,0001) and (0002,0012) will be added if not already present and the
    other required elements will be checked to see if they exist. If
    `enforce_standard` is ``False`` then `file_meta` will be written as is
    after minimal validation checking.

    The following Type 3/1C Elements may also be present:

    * (0002,0013) *Implementation Version Name*, SH, N
    * (0002,0016) *Source Application Entity Title*, AE, N
    * (0002,0017) *Sending Application Entity Title*, AE, N
    * (0002,0018) *Receiving Application Entity Title*, AE, N
    * (0002,0102) *Private Information*, OB, N
    * (0002,0100) *Private Information Creator UID*, UI, N

    If `enforce_standard` is ``True`` then (0002,0013) will be added/updated.

    *Encoding*

    The encoding of the *File Meta Information* shall be *Explicit VR Little
    Endian*.

    Parameters
    ----------
    fp : file-like
        The file-like to write the File Meta Information to.
    file_meta : pydicom.dataset.Dataset
        The File Meta Information elements.
    enforce_standard : bool
        If ``False``, then only the *File Meta Information* elements already in
        `file_meta` will be written to `fp`. If ``True`` (default) then a DICOM
        Standards conformant File Meta will be written to `fp`.

    Raises
    ------
    ValueError
        If `enforce_standard` is ``True`` and any of the required *File Meta
        Information* elements are missing from `file_meta`, with the
        exception of (0002,0000), (0002,0001) and (0002,0012).
    ValueError
        If any non-Group 2 Elements are present in `file_meta`.
    FileMetaInformationGroupLengthr   TF   i   N)r   r  r   rZ   r   r   r   r  r   r   r   )r   r
  r  r   rP   rP   rT   write_file_meta_info  s   
B

r  tsyntaximplicit_vrlittle_endianforce_encodingc                 C   sP  ||f}|rd|v rt dttttf |S |dur#|du r#|df}d}tjs.| j| jf}d}d|vr7|}nd|vr>|}nd| jvrF| j}|du r[d|vrWttttf |S t d|j	rr|j
srd|v rit dttttf |S |j
s~t d|j d|dur||jkrt d	|j d
|dur||jkrt d|j d
|j|jfS )a  Return the encoding to use for `ds`.

    If `force_encoding` isn't ``True`` the priority is:

    1. The encoding corresponding to `tsyntax`
    2. The encoding set by `implicit_vr` and `little_endian`
    3. `Dataset.is_implicit_VR` and `Dataset.is_little_endian`
    4. `Dataset.original_encoding`

    If none of those are valid, raise an exception.

    If `force_encoding` is ``True`` then `implicit_vr` and `little_endian` are
    required.

    Parameters
    ----------
    ds : pydicom.dataset.Dataset
        The dataset that is to be encoded.
    tsyntax : pydicom.uid.UID | None
        The dataset's public or private transfer syntax (if any). Private
        transfer syntaxes require `implicit_vr` and `little_endian` be used.
    implicit_vr : bool | None
        The VR encoding method (if supplied)
    little_endian : bool | None
        The encoding endianness (if supplied).
    force_encoding : bool
        If ``True`` then force the encoding to use `implicit_vr` and
        `little_endian`. Default ``False``.

    Returns
    -------
    tuple[bool, bool]
        The encoding to use as ``[use implicit VR, use little endian]``.

    Raises
    ------
    ValueError
        If unable to determine the encoding to use, if `transfer_syntax` is
        not a transfer syntax, or if there's an inconsistency between
        `transfer_syntax` and `implicit_vr` or `little_endian`.
    NzJ'implicit_vr' and 'little_endian' are required if 'force_encoding' is usedTr   zUnable to determine the encoding to use for writing the dataset, please set the file meta's Transfer Syntax UID or use the 'implicit_vr' and 'little_endian' argumentszaThe 'implicit_vr' and 'little_endian' arguments are required when using a private transfer syntaxzThe Transfer Syntax UID 'z ' is not a valid transfer syntaxzQThe 'implicit_vr' value is not consistent with the required VR encoding for the 'z' transfer syntaxzRThe 'little_endian' value is not consistent with the required endianness for the ')r   r
   r   r   r   r   r   rZ   rk   
is_privateis_transfer_syntaxname)rz   r  r  r  r  arg_encodingr   fallback_encodingrP   rP   rT   _determine_encoding  s`   0
r  F)r  r  enforce_file_formatr  	overwrite__write_like_originalfilenamer  r  kwargsc            
   K   s  | dd}	d||	fvrtjrtdtd|	du r|}	|	dur0tjr(tdtdt |	 }dd | D }
|
rEtdd	|
 |jj	}d
d |j
D }|rcd|v r[tdtd| d|rk|rktdt }t|drxt|j}| dd}t|||||}|s|dkrtdt|dd}|rt|dkrtd| d|r|du r|dkrt|_n|dkrt|_| dd}| dd}| dd}|du s|r||kr||_| dd}| dd}|du s|r||kr||_t|dd |sd }|r|js|jrd!|v r|j|d! _d}t| } t| tr.|s$d"nd#}t | |}d$}n(t| t!r7| }nzt!| }W n t"yU } ztd%t#| j	 |d}~ww |\|_$|_%zd|rj|&| |&d& |rtt'|||d |t(krt) }|\|_$|_%t*|| t+j,t+j- d'}t.|/|0 }||1 7 }|&| t|d( r|&d) nt*|| W |s|2  dS dS |s|2  w w )*a  Write `dataset` to `filename`, which can be a path, a file-like or a
    writeable buffer.

    .. versionchanged:: 3.0

        Added the `enforce_file_format` and `overwrite` keyword arguments.

    .. deprecated:: 3.0

        `write_like_original` is deprecated and will be removed in v4.0, use
        `enforce_file_format` instead.

    If `enforce_file_format` is ``True`` then an attempt will be made to write
    `dataset` using the :dcm:`DICOM File Format <part10/chapter_7.html>`, or
    raise an exception if unable to do so.

    If `enforce_file_format` is ``False`` (default) then `dataset` will be
    written as-is (after minimal validation checking) and may or may not
    contain all or parts of the *File Meta Information* and hence may or may
    not be conformant with the DICOM File Format.

    **DICOM File Format**

    The *DICOM File Format* consists of a 128-byte preamble, a 4 byte
    ``b'DICM'`` prefix, the *File Meta Information Group* elements and finally
    the encoded `dataset`.

    **Preamble and Prefix**

    The ``dataset.preamble`` attribute shall be 128-bytes long or ``None``. The
    actual preamble written depends on `enforce_file_format` and
    ``dataset.preamble`` (see the table below).

    +------------------+------------------------------+
    |                  | enforce_file_format          |
    +------------------+-------------+----------------+
    | dataset.preamble | False       | True           |
    +==================+=============+================+
    | None             | no preamble | 128 0x00 bytes |
    +------------------+-------------+----------------+
    | 128 bytes        | dataset.preamble             |
    +------------------+------------------------------+

    The prefix shall be the bytestring ``b'DICM'`` and will be written if and
    only if the preamble is present.

    **File Meta Information Group Elements**

    The preamble and prefix are followed by a set of DICOM elements from the
    (0002,eeee) group. Some of these elements are required (Type 1) while
    others are optional (Type 3/1C). If `enforce_file_format` is ``False``
    then the *File Meta Information Group* elements are all optional, otherwise
    an attempt will be made to add the required elements using `dataset`. See
    :func:`~pydicom.filewriter.write_file_meta_info` for more information on
    which elements are required.

    The *File Meta Information Group* elements must be included within their
    own :class:`~pydicom.dataset.FileMetaDataset` in the ``dataset.file_meta``
    attribute.

    *Encoding*

    The preamble and prefix are encoding independent. The *File Meta
    Information Group* elements are encoded as *Explicit VR Little Endian* as
    required by the DICOM Standard.

    **Dataset**

    A DICOM Dataset representing a SOP Instance related to a DICOM Information
    Object Definition (IOD). It's up to the user to ensure `dataset` conforms
    to the requirements of the IOD.

    *Encoding*

    .. versionchanged:: 3.0

        Added the `implicit_vr` and `little_endian` arguments.

    The `dataset` is encoded as specified by (in order of priority):

    * The encoding corresponding to the set *Transfer Syntax UID* in
      :attr:`~pydicom.dataset.FileDataset.file_meta`.
    * The `implicit_vr` and `little_endian` arguments
    * :attr:`~pydicom.dataset.Dataset.is_implicit_VR` and
      :attr:`~pydicom.dataset.Dataset.is_little_endian`
    * :attr:`~pydicom.dataset.Dataset.original_encoding`

    .. warning::

        This function does not automatically convert `dataset` from little
        to big endian encoding (or vice versa). The endianness of values for
        elements with a VR of **OD**, **OF**, **OL**, **OW**, **OV** and
        **UN** must be converted manually prior to calling
        :func:`~pydicom.filewriter.dcmwrite`.

    Parameters
    ----------
    filename : str, PathLike, file-like or writeable buffer
        File path, file-like or writeable buffer to write the encoded `dataset`
        to. If using a writeable buffer it must have ``write()``, ``seek()``
        and ``tell()`` methods.
    dataset : pydicom.dataset.FileDataset
        The dataset to be encoded.
    write_like_original : bool, optional
        If ``True`` (default) then write `dataset` as-is, otherwise
        ensure that `dataset` is written in the DICOM File Format or
        raise an exception if that isn't possible. This parameter is
        deprecated, please use `enforce_file_format` instead.
    implicit_vr : bool, optional
        Required if `dataset` has no valid public *Transfer Syntax UID*
        set in the file meta and `dataset` has been created from scratch. If
        ``True`` then encode `dataset` using implicit VR, otherwise use
        explicit VR.
    little_endian : bool, optional
        Required if `dataset` has no valid public *Transfer Syntax UID*
        set in the file meta and `dataset` has been created from scratch. If
        ``True`` (default) then use little endian byte order when encoding
        `dataset`, otherwise use big endian.
    enforce_file_format : bool, optional
        If ``True`` then ensure `dataset` is written in the DICOM File
        Format or raise an exception if that isn't possible.

        If ``False`` (default) then write `dataset` as-is, preserving the
        following - which may result in a non-conformant file:

        - ``dataset.preamble``: if `dataset` has no preamble then none will
          be written
        - ``dataset.file_meta``: if `dataset` is missing any required *File
          Meta Information Group* elements then they will not be written.
    force_encoding : bool, optional
        If ``True`` then force the encoding to follow `implicit_vr` and
        `little_endian`. Cannot be used with `enforce_file_format`. Default
        ``False``.
    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``).

    Raises
    ------
    ValueError

      * If group ``0x0000`` *Command Set* elements are present in `dataset`.
      * If group ``0x0002`` *File Meta Information Group* elements are present
        in `dataset`.
      * If ``dataset.preamble`` exists but is not 128 bytes long.

    See Also
    --------
    pydicom.dataset.Dataset
        Dataset class with relevant attributes and information.
    pydicom.dataset.Dataset.save_as
        Encode a dataset and write it to file, wraps ``dcmwrite()``.
    write_like_originalNzr'write_like_original' is no longer accepted as a positional or keyword argument, use 'enforce_file_format' insteadzN'write_like_original' cannot be used as both a positional and keyword argumentzi'write_like_original' is deprecated and will be removed in v4.0, please use 'enforce_file_format' insteadc                 S   s   g | ]}|d kr|qS )r  rP   rQ   rP   rP   rT   r   '  rV   zdcmwrite.<locals>.<listcomp>z,Invalid keyword argument(s) for dcmwrite(): z, c                 S   s    g | ]}|d ? dv r|d ? qS )rO   )r   rW   rP   rQ   rP   rP   rT   r   0  s     r   zcCommand Set elements (0000,eeee) are not allowed when using dcmwrite(), use write_dataset() insteadz_File Meta Information Group elements (0002,eeee) must be in a FileMetaDataset instance in the 'z.file_meta' attributez:'force_encoding' cannot be used with 'enforce_file_format'r
  TransferSyntaxUID)TFz>Implicit VR and big endian is not a valid encoding combinationpreamble   r   z!.preamble' must be 128-bytes long)TT)FFMediaStorageSOPClassUIDSOPClassUIDMediaStorageSOPInstanceUIDSOPInstanceUIDT)r  s                                                                                                                                   re   xbwbFzGdcmwrite: Expected a file path, file-like or writeable buffer, but got s   DICM)wbitsrW   r   )3r   r   r   r  r   DeprecationWarningr   r   	__class____name___dictr   r   rc   r   r
  r  r_   r   r*   r  r+   r"  r$  r   r  r  is_compressedri   r   rt   r   r   r   r   typer   rZ   r   r  r(   r   r   zlibcompressobj	MAX_WBITS	bytearraycompressr   flushclose)r  r   r  r  r  r  r  r  r  r  r   cls_namebad_tagsr
  r  encodingr   
meta_classds_classmeta_instanceds_instancecaller_owns_file	file_moder   r   r   
compressordeflatedrP   rP   rT   dcmwrite[  s    ,












rA  dflrg   qLrf   Qr   )r   )T)__doc__collections.abcr   r   r   copyr   ior   structr   typingr   r	   r
   r   r/  pydicomr   pydicom.charsetr   r   r   pydicom.dataelemr   r   r   pydicom.datasetr   r   r   pydicom.filebaser   r   r   r   pydicom.fileutilr   r   r   r   r   pydicom.miscr   pydicom.multivalr    pydicom.tagr!   r"   r#   r$   r%   r&   r'   pydicom.uidr(   r)   r*   r+   pydicom.valuerepr,   r-   r.   r/   r0   r1   r2   r3   r4   r5   pydicom.valuesr6   r   r   rn   rv   rangery   r   r   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   EncodingTyper`   r   r   r   r  r	  r  r  rA  AEASATCSDSFDFLLOLTrj   ODOFOLrl   OVPNSHSLr   rq   STSVUCUIULr   URrp   UTUVUS_SSUS_OWUS_SS_OWOB_OWr   rP   rP   rP   rT   <module>   s  $	0
}

;

<'	





|

U 
`

y
	

  `








	























 
!
"
#



