o
    RŀgcP                     @   s   d 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m	Z	 ddl
mZ dd	lmZ i Zee ee dddZdd ZG dd deZdd ZdZdZdZdd Zdd ZedkrnddlmZ edd dS dS )zABio.SeqIO support for accessing sequences in PDB and mmCIF files.    N)BiopythonParserWarning)protein_letters_3to1)protein_letters_3to1_extended)Seq)	SeqRecord   )SequenceIteratorXc                 C   s$   t | trt| |S t| j|S )zjReturn the one-letter amino acid code from the residue name.

    Non-amino acid are returned as "X".
    )
isinstancestr_aa3to1_dictgetresname)residue
undef_code r   C/var/www/html/myenv/lib/python3.10/site-packages/Bio/SeqIO/PdbIO.py_res2aacode   s   
r   c              	   c   s   |d }t |j D ]\}}dd | D }|sqg }dd |D }t|dd D ]$\}}	||d  |	d krQ||d  |	krQ||d |	||d  f q-|rg }
d}|D ]<\}}}||kr|| d }|
dd	 ||| D  |}|
d
|  qZtdt	 |
dd	 ||| D   n|
dd	 ||d D  ndd |D }
|  d| }t
td|
||d}d|jd< |j|jd< |j|jd< t|d |jd< t|d |jd< |V  qdS )a_  Return SeqRecords from Structure objects.

    Base function for sequence parsers that read structures Bio.PDB parsers.

    Once a parser from Bio.PDB has been used to load a structure into a
    Bio.PDB.Structure.Structure object, there is no difference in how the
    sequence parser interprets the residue sequence. The functions in this
    module may be used by SeqIO modules wishing to parse sequences from lists
    of residues.

    Calling functions must pass a Bio.PDB.Structure.Structure object.


    See Bio.SeqIO.PdbIO.PdbAtomIterator and Bio.SeqIO.PdbIO.CifAtomIterator for
    details.
    r   c                 S   s$   g | ]}t |  d kr|qS r	   )r   get_resnameupper.0resr   r   r   
<listcomp>8   s
    z AtomIterator.<locals>.<listcomp>c                 S   s   g | ]}|j d  qS )r   )id)r   rr   r   r   r   B   s    Nr   c                 s       | ]}t |V  qd S Nr   r   xr   r   r   	<genexpr>M       zAtomIterator.<locals>.<genexpr>r	   z*Ignoring out-of-order residues after a gapc                 s   r   r   r    r!   r   r   r   r#   W   r$   c                 s   r   r   r    r!   r   r   r   r#   [   r$   c                 S      g | ]}t |qS r   r    r!   r   r   r   r   ^       : )r   descriptionproteinmolecule_typemodelchainstartend)sorted
child_dictitemsget_unpacked_list	enumerateappendextendwarningswarnr   r   r   joinannotationsr   int)pdb_id	structurer,   chn_idr-   residuesgapsrnumbersirnumres_outprev_idxpregappostgapgapsize	record_idrecordr   r   r   AtomIterator$   sR   $
rK   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )PdbSeqresIteratorzParser for PDB files.c                    s   t  j|ddd dS )ap  Return SeqRecord objects for each chain in a PDB file.

        Arguments:
         - source - input stream opened in text mode, or a path to a file

        The sequences are derived from the SEQRES lines in the
        PDB file header, not the atoms of the 3D structure.

        Specifically, these PDB records are handled: DBREF, DBREF1, DBREF2, SEQADV, SEQRES, MODRES

        See: http://www.wwpdb.org/documentation/format23/sect3.html

        This gets called internally via Bio.SeqIO for the SEQRES based interpretation
        of the PDB file format:

        >>> from Bio import SeqIO
        >>> for record in SeqIO.parse("PDB/1A8O.pdb", "pdb-seqres"):
        ...     print("Record id %s, chain %s" % (record.id, record.annotations["chain"]))
        ...     print(record.dbxrefs)
        ...
        Record id 1A8O:A, chain A
        ['UNP:P12497', 'UNP:POL_HV1N5']

        Equivalently,

        >>> with open("PDB/1A8O.pdb") as handle:
        ...     for record in PdbSeqresIterator(handle):
        ...         print("Record id %s, chain %s" % (record.id, record.annotations["chain"]))
        ...         print(record.dbxrefs)
        ...
        Record id 1A8O:A, chain A
        ['UNP:P12497', 'UNP:POL_HV1N5']

        Note the chain is recorded in the annotations dictionary, and any PDB DBREF
        lines are recorded in the database cross-references list.
        tPDB)modefmtN)super__init__)selfsource	__class__r   r   rR   t   s   %zPdbSeqresIterator.__init__c                 C   s   |  |}|S )z9Start parsing the file, and return a SeqRecord generator.)iterate)rS   handlerecordsr   r   r   parse   s   
zPdbSeqresIterator.parsec              	   c   sZ   t t}t t}d}|D ]}|dd  }|dkr6|d }dd |dd  D }|| | q|d	kri|d
d }|d }|dd  }	|dd  }
|dd  }|| ||	|
|d q|dkr|d
d }|d }|dd  }	|dd  }q|dkr||d
d ks||d krtd|dd  }
|| ||	|
|d q|du rtdt|	 D ]i\}}t
td|}d|i|_d|jd< ||v r$|| d }|d  d |  |_|_|d!  d |d"  d#|d$  |_|| D ]}|j|d!  d |d"  |d!  d |d$  g qn||_|V  qdS )%z)Iterate over the records in the PDB file.Nr      SEQRES   c                 S   r%   r   r    r   r   r   r   r      r&   z-PdbSeqresIterator.iterate.<locals>.<listcomp>   DBREF             !   )   *   6   )r<   databasedb_acc
db_id_codeDBREF1/   C   DBREF2zDBREF2 identifiers do not match   (   zEmpty file.r(   r-   r*   r+   r<   r'   rh   ri    rj   )collectionsdefaultdictliststripsplitr6   r5   
ValueErrorr0   r2   r   r   r9   r:   r   namer)   dbxrefs)rS   rX   chainsmetadatarec_nameliner>   r?   r<   rh   ri   rj   rJ   mmelemr   r   r   rW      sx   

	




"zPdbSeqresIterator.iterate)__name__
__module____qualname____doc__rR   rZ   rW   __classcell__r   r   rU   r   rL   q   s
    'rL   c                 c   sb    ddl m} | d| }|jd }|stdt d}t||D ]}|j	|j |V  q"dS )a  Return SeqRecord objects for each chain in a PDB file.

    Argument source is a file-like object or a path to a file.

    The sequences are derived from the 3D structure (ATOM records), not the
    SEQRES lines in the PDB file header.

    Unrecognised three letter amino acid codes (e.g. "CSD") from HETATM entries
    are converted to "X" in the sequence.

    In addition to information from the PDB header (which is the same for all
    records), the following chain specific information is placed in the
    annotation:

    record.annotations["residues"] = List of residue ID strings
    record.annotations["chain"] = Chain ID (typically A, B ,...)
    record.annotations["model"] = Model ID (typically zero)

    Where amino acids are missing from the structure, as indicated by residue
    numbering, the sequence is filled in with 'X' characters to match the size
    of the missing region, and  None is included as the corresponding entry in
    the list record.annotations["residues"].

    This function uses the Bio.PDB module to do most of the hard work. The
    annotation information could be improved but this extra parsing should be
    done in parse_pdb_header, not this module.

    This gets called internally via Bio.SeqIO for the atom based interpretation
    of the PDB file format:

    >>> from Bio import SeqIO
    >>> for record in SeqIO.parse("PDB/1A8O.pdb", "pdb-atom"):
    ...     print("Record id %s, chain %s" % (record.id, record.annotations["chain"]))
    ...
    Record id 1A8O:A, chain A

    Equivalently,

    >>> with open("PDB/1A8O.pdb") as handle:
    ...     for record in PdbAtomIterator(handle):
    ...         print("Record id %s, chain %s" % (record.id, record.annotations["chain"]))
    ...
    Record id 1A8O:A, chain A

    r   )	PDBParserNidcodez0'HEADER' line not found; can't determine PDB ID.????)
Bio.PDBr   get_structureheaderr7   r8   r   rK   r:   update)rT   r   r=   r<   rJ   r   r   r   PdbAtomIterator  s   1
r   )_pdbx_poly_seq_scheme.asym_id_pdbx_poly_seq_scheme.mon_id)_struct_ref.id_struct_ref.db_name_struct_ref.db_code_struct_ref.pdbx_db_accession)_struct_ref_seq.ref_id _struct_ref_seq.pdbx_PDB_id_code_struct_ref_seq.pdbx_strand_idc              	   c   s   ddl m} tt}tt}|| }tt t D ]}||vr&g ||< qt|| ts4|| g||< qt	|d |d D ]\}}t
|}|| | q>i }	t	|d |d |d |d D ]\}
}}}|||d	|	|
< q_t	|d
 |d |d D ]\}
}}|	|
 }|| d|i || d | qzt| D ]g\}}ttd|}d|i|_d|jd< ||v r|| d }|d  d|  |_|_|d  d|d  d|d  |_|| D ]}|j|d  d|d  |d  d|d  g qn||_|V  qdS )a  Return SeqRecord objects for each chain in an mmCIF file.

    Argument source is a file-like object or a path to a file.

    The sequences are derived from the _entity_poly_seq entries in the mmCIF
    file, not the atoms of the 3D structure.

    Specifically, these mmCIF records are handled: _pdbx_poly_seq_scheme and
    _struct_ref_seq. The _pdbx_poly_seq records contain sequence information,
    and the _struct_ref_seq records contain database cross-references.

    See:
    http://mmcif.wwpdb.org/dictionaries/mmcif_pdbx_v40.dic/Categories/pdbx_poly_seq_scheme.html
    and
    http://mmcif.wwpdb.org/dictionaries/mmcif_pdbx_v50.dic/Categories/struct_ref_seq.html

    This gets called internally via Bio.SeqIO for the sequence-based
    interpretation of the mmCIF file format:

    >>> from Bio import SeqIO
    >>> for record in SeqIO.parse("PDB/1A8O.cif", "cif-seqres"):
    ...     print("Record id %s, chain %s" % (record.id, record.annotations["chain"]))
    ...     print(record.dbxrefs)
    ...
    Record id 1A8O:A, chain A
    ['UNP:P12497', 'UNP:POL_HV1N5']

    Equivalently,

    >>> with open("PDB/1A8O.cif") as handle:
    ...     for record in CifSeqresIterator(handle):
    ...         print("Record id %s, chain %s" % (record.id, record.annotations["chain"]))
    ...         print(record.dbxrefs)
    ...
    Record id 1A8O:A, chain A
    ['UNP:P12497', 'UNP:POL_HV1N5']

    Note the chain is recorded in the annotations dictionary, and any mmCIF
    _struct_ref_seq entries are recorded in the database cross-references list.
    r   )
MMCIF2Dictr   r   r   r   r   r   )rh   rj   ri   r   r   r   r<   r   r(   r-   r*   r+   r'   rh   ri   rq   rj   N)Bio.PDB.MMCIF2Dictr   rr   rs   rt   PDBX_POLY_SEQ_SCHEME_FIELDSSTRUCT_REF_SEQ_FIELDSSTRUCT_REF_FIELDSr
   zipr   r5   r   r0   r2   r   r   r9   r:   r   rx   r)   ry   r6   )rT   r   rz   r{   rY   fieldasym_idmon_id	mon_id_1lstruct_refsref_iddb_namedb_coderi   r<   chain_id
struct_refr>   r?   rJ   r~   r   r   r   r   CifSeqresIteratorc  sn   *





"r   c                 c   sN    ddl m} | d| }|jd }|stdt d}t||E dH  dS )a  Return SeqRecord objects for each chain in an mmCIF file.

    Argument source is a file-like object or a path to a file.

    The sequences are derived from the 3D structure (_atom_site.* fields)
    in the mmCIF file.

    Unrecognised three letter amino acid codes (e.g. "CSD") from HETATM entries
    are converted to "X" in the sequence.

    In addition to information from the PDB header (which is the same for all
    records), the following chain specific information is placed in the
    annotation:

    record.annotations["residues"] = List of residue ID strings
    record.annotations["chain"] = Chain ID (typically A, B ,...)
    record.annotations["model"] = Model ID (typically zero)

    Where amino acids are missing from the structure, as indicated by residue
    numbering, the sequence is filled in with 'X' characters to match the size
    of the missing region, and  None is included as the corresponding entry in
    the list record.annotations["residues"].

    This function uses the Bio.PDB module to do most of the hard work. The
    annotation information could be improved but this extra parsing should be
    done in parse_pdb_header, not this module.

    This gets called internally via Bio.SeqIO for the atom based interpretation
    of the PDB file format:

    >>> from Bio import SeqIO
    >>> for record in SeqIO.parse("PDB/1A8O.cif", "cif-atom"):
    ...     print("Record id %s, chain %s" % (record.id, record.annotations["chain"]))
    ...
    Record id 1A8O:A, chain A

    Equivalently,

    >>> with open("PDB/1A8O.cif") as handle:
    ...     for record in CifAtomIterator(handle):
    ...         print("Record id %s, chain %s" % (record.id, record.annotations["chain"]))
    ...
    Record id 1A8O:A, chain A

    r   )MMCIFParserNr   zCould not determine the PDB ID.r   )Bio.PDB.MMCIFParserr   r   r   r7   r8   r   rK   )rT   r   r=   r<   r   r   r   CifAtomIterator  s   1
r   __main__)run_doctest)verboser   )r   rr   r7   Bior   Bio.Data.PDBDatar   r   Bio.Seqr   Bio.SeqRecordr   
Interfacesr   r   r   r   rK   rL   r   r   r   r   r   r   r   
Bio._utilsr   r   r   r   r   <module>   s4   


M Dq;