o
    iC                     @   s^  d 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	 ddl
mZ ddlZddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZmZmZ ddlmZmZ dZedZe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 fddZ$				d:dede de%dB de&d edB de fd!d"Z'ddde#dfdede de%dB de&d#e	e ge f d edB de fd$d%Z(					d;dede de%dB de&d&e&d edB de fd'd(Z)	d<d)e de%dB de&de fd*d+Z*	d<dede%dB de&de fd,d-Z+d.ej,d/e%ddfd0d1Z-d2ej.ddfd3d4Z/d=d/e%d2e0e  dB ddfd5d6Z1e2d7kr-e1d8d9 dS dS )>z
Produce runnable python code which can recreate DICOM objects or files.

Can run as a script to produce code for an entire file,
or import and use specific functions to provide code for pydicom DICOM classes

    N)cast)Callable)deque)dictionary_keyword)DataElement)Dataset)BaseTag)BYTES_VRAMBIGUOUS_VRVR)filespec_helpfilespec_parser
z(.)([A-Z][a-z]+)z([a-z0-9])([A-Z])namereturnc                 C   s   t d| }td| S )z:Convert name from CamelCase to lower_case_with_underscoresz\1_\2)first_cap_resub
all_cap_relower)r   s1 r   I/mnt/sdb/aimis/docanh/lib/python3.10/site-packages/pydicom/util/codify.pycamel_to_underscore)   s   r   tagc                 C   s   d| j dd| jddS )z'String of tag value as (0xgggg, 0xeeee)z(0x04Xz, 0x))groupelement)r   r   r   r   tag_repr0   s   r   c                 C   s0   t | } | dd} | dd} | dd} | S )zCallable to reduce some names in code to more readable short form

    :arg name: a sequence variable name or sequence item name
    :return: a shorter version of name if a known conversion,
             else return original name

    control_pointcp	referencereffraction_groupfrxn_gp)r   replace)r   r   r   r   default_name_filter5   s
   r&   c                  C   s   d} d}d}t | ||fS )zpCode the import statements needed by other codify results

    :return: a string of import statement lines

    zimport pydicomz4from pydicom.dataset import Dataset, FileMetaDatasetz%from pydicom.sequence import Sequence)	line_termjoin)line1line2line3r   r   r   code_importsE   s   r,   dsFdataelemdataset_nameexclude_sizeinclude_private	var_namesc                 C   s   | j t jkrt| ||||dS d}zt| j}W n ty#   d}Y nw | j dkr/t| j}nt| j}|rY| j t	t
B t jh v rYt| jttB sYt| j|krYdt| j d}|rg| d| d| }|S t| j}	| j }
| d	|	 d
|
 d| d}|S )a  Code lines for a single DICOM data element

    Parameters
    ----------

    dataelem : DataElement
        The DataElement instance to turn into code
    dataset_name : str
        The variable name of the Dataset containing `dataelem`
    exclude_size : int | None
        If specified, values longer than this (in bytes)
        will only have a commented string for a value,
        causing a syntax error when the code is run,
        and thus prompting the user to remove or fix that line.
    var_names: deque | None
        Used internally to ensure unique variable names in nested sequences.
    Returns
    -------
    str
        A string containing code to recreate the data element
        If the data element is a sequence, calls code_sequence
    r2   TFATz# XXX Array of z bytes excluded. = z	.add_new(z, 'z', r   )r   SQcode_sequencer   r   KeyErrorr   valuereprr	   r
   US_SS
isinstanceintfloatlen)r.   r/   r0   r1   r2   have_keywordkeywordvaluerepliner   vrr   r   r   code_dataelemQ   s4   



rF   name_filterc                    s   du rt   dtdtf fdd}g }| j}| j}	|	dd}
zt| j}W n ty7   d| jd	}Y nw |d |d
|	  ||} | |}||}||d  ||d | d |  t	|D ]\}}|ddd }|ddd }t
||rtt||}nt
||rtt||}nt|d }|d |d
|	 d |
 d |  |dd| } | ||}t|||| d}   | }||d  || d| d ||dd  qk   t|S )a  Code lines for recreating a Sequence data element

    Parameters
    ----------
    dataelem : DataElement
        The DataElement instance whose value is the Sequence
    dataset_name : str
        Variable name of the dataset containing the Sequence
    exclude_size : int, optional
        If not ``None``, values longer than this (in bytes) will only have a
        commented string for a value, causing a syntax error when the code is
        run, and thus prompting the user to remove or fix that line.
    include_private: bool
        If ``False`` (default) private elements are skipped, otherwise private
        data elements will be coded.
    name_filter: Callable[[str], str]
        A callable taking a sequence name or sequence item name, and returning
        a shorter name for easier code reading
    var_names: deque | None
        Used internally to ensure unique variable names in nested sequences.

    Returns
    -------
    str
        A string containing code lines to recreate a DICOM sequence
    Nr   r   c                    s.   t t | d }|dkr| S | d|  S )N   r   _)r   r   count)r   
name_countr3   r   r   unique_name   s   z"code_sequence.<locals>.unique_namez	 Sequence Tag08xz# z = Sequence()r5   r6   SequenceIndexNumberrH   z:  	_sequencer3   r   z.append(r   )r   strr:   r   r%   r   r   r9   append	enumeratehasattrgetattrcode_datasetpop
splitlinesextendr'   r(   )r.   r/   r0   r1   rG   r2   rL   linesseqseq_nameseq_item_nameseq_keywordseq_varorig_seq_varir-   index_keywordnumber_keyword	index_strds_name	code_item
code_splitr   r3   r   r8      sV   %







r8   is_file_metac           
      C   s   |du rt  }g }|rdnd}|||  | D ]"}|s!|jjr!qt|||||d}	||	 |jtjkr:|d qt|rI|d dkrI|  t	
|S )a  Return Python code for creating `ds`.

    Parameters
    ----------
    ds : pydicom.dataset.Dataset
        The dataset to codify.
    dataset_name : str, optional
        The Python variable name to use for the dataset, default ``'ds'``.
    exclude_size : int, optional
        If not ``None``, values longer than this (in bytes) will only have a
        commented string for a value, causing a syntax error when the code is
        run, and thus prompting the user to remove or fix that line.
    include_private : bool, optional
        If ``False`` (default) private elements are skipped, otherwise private
        data elements will be coded.
    is_file_meta : bool, optional
        ``True`` if `ds` contains file meta information elements.
    var_names: deque, optional
        Used internally to ensure unique variable names in nested sequences.

    Returns
    -------
    str
        The codified dataset.
    Nz = FileMetaDataset()z = Dataset()r3   rM   )r   rV   r   
is_privaterF   r   r7   r@   r[   r'   r(   )
r-   r/   r0   r1   rl   r2   r^   ds_classr.   	code_liner   r   r   rZ   	  s$   "



rZ   filenamec                 C   s   t j| dd}t|||S )a  Write a complete source code file to recreate a DICOM file

    Parameters
    ----------
    filename : str
        Complete path and filename of a DICOM file to convert
    exclude_size : int |None
        If not None, values longer than this (in bytes)
        will only have a commented string for a value,
        causing a syntax error when the code is run,
        and thus prompting the user to remove or fix that line.
    include_private : bool
        If ``False`` (default), private elements are skipped
        If ``True``, private data elements will be coded.

    Returns
    -------
    str
        A string containing code lines to recreate the entire DICOM file

    T)force)pydicomdcmreadcode_file_from_dataset)rq   r0   r1   r-   r   r   r   	code_fileF  s   rv   c           
      C   s  g }|  d}|rd| dnd}|d |d|  |d |t  |d t| d	rL|d
 t| jd	||dd}|| |d |d t| ||d}|| |d t| d	rl|d | j\}}	|d| d|	 d t|S )a  Write a complete source code file to recreate a DICOM file

    Parameters
    ----------
    ds : Dataset
        A pydicom Dataset to convert
    exclude_size : int |None
        If not None, values longer than this (in bytes)
        will only have a commented string for a value,
        causing a syntax error when the code is run,
        and thus prompting the user to remove or fix that line.
    include_private : bool
        If ``False`` (default), private elements are skipped
        If ``True``, private data elements will be coded.

    Returns
    -------
    str
        A string containing code lines to recreate the entire DICOM file

    rq   zDICOM file ''znon-file datasetz# -*- coding: utf-8 -*-z# Coded version of z+# Produced by pydicom codify utility scriptrM   	file_metaz# File meta info data elementsT)rl   z# Main data elements)r0   r1   zds.file_meta = file_metazds.set_original_encoding(z, r   )	getrV   r,   rX   rZ   rx   original_encodingr'   r(   )
r-   r0   r1   r^   rq   
identifier	code_metacode_dsimplicit_vrlittle_endianr   r   r   ru   b  s<   














ru   parserdefault_exclude_sizec                 C   sr   | j dttd | j ddtjddddtjd	 | j d
dt|d| dd | j ddddd | j dddd d S )Nfilespec)helptypeoutfile?wzUTF-8)encodingzQFilename to write Python code to, if not specified then code is written to stdout)nargsr   r   defaultz-ez--exclude-sizez4Exclude binary data larger than specified (default: z bytes))r   r   r   z-pz--include-private
store_truez:Include private data elements (default is to exclude them))actionr   z-sz	--save-aszjSpecify the filename for ds.save_as(save_filename); otherwise the input name + '_from_codify' will be used)r   )add_argumentr   r   argparseFileTypesysstdoutr>   )r   r   r   r   r   set_parser_arguments  s@   


r   argsc           	      C   s   t | jdkrtd| jd \}}|j}|r%t|ts%tdt| t|p)|| j| j	}| j
r6| j
}ntj|\}}|d d }d| d}||7 }z| jjd	kr_td
| jj d W n	 tyi   Y nw | j| d S )NrH   z1Codify can only work on a single DICOM file inputr   z&Codify can only code a Dataset, not a _from_codifyz.dcmz
ds.save_as(r'z', enforce_file_format=True)z<stdout>zWriting code to file 'rw   )r@   r   NotImplementedErrorrq   r=   r   r   ru   r0   r1   save_asospathsplitextr   r   printAttributeErrorwrite)	r   r-   r   rq   code_strsave_as_filenamebaserI   	save_liner   r   r   	do_codify  s2   r   c                 C   s2   t jdd|  dd}t||  t|| dS )a7  Create Python code according to user options

    Parameters:
    -----------
    default_exclude_size : int
        Values longer than this will be coded as a commented syntax error
    args : List[str], optional
        Command-line arguments to parse.  If ``None`` then :attr:`sys.argv` is
        used.
    z-Produce python/pydicom code from a DICOM filez>Binary data (e.g. pixels) larger than --exclude-size (default zy bytes) is not included. A dummy line with a syntax error is produced. Private data elements are not included by default.)descriptionepilogN)r   ArgumentParserr   r   
parse_args)r   r   r   r   r   r   main  s   
	r   __main__d   )r   )r-   NFN)r-   NFFN)NF)N)3__doc__r   os.pathr   rer   typingr   collections.abcr   collectionsr   rs   pydicom.datadictr   pydicom.dataelemr   pydicom.datasetr   pydicom.tagr   pydicom.valuerepr	   r
   r   pydicom.cli.mainr   r   r'   compiler   r   rU   r   r   r&   r,   r>   boolrF   r8   rZ   rv   ru   r   r   	Namespacer   listr   __name__r   r   r   r   <module>   s   


F
v
>

F
, $
