
     i                         d Z ddlmZ ddlZddlZddlZddlmZm	Z	 ddl
mZ ddlmZ  G d d	e          Z G d
 dee          Zd Zd Zd ZdS )a  
Base topology reader classes --- :mod:`MDAnalysis.topology.base`
================================================================

Derive topology reader classes from the base class in this module. All
topology readers raise :exc:`IOError` upon failing to read a topology
file and :exc:`ValueError` upon failing to make sense of the read data.

Classes
-------

.. autoclass:: TopologyReaderBase
   :members:
   :inherited-members:

    )reduceN   )_PARSERS_PARSER_HINTS)IOBase)utilc                       e Zd ZdZd ZdS )_Topologymetaa  Internal: Topology Parser registration voodoo

    When classes which inherit from TopologyReaderBase are *defined*
    this metaclass makes it known to MDAnalysis.  The optional `format`
    attribute and `_format_hint` staticmethod are read:
     - `format` defines the file extension this Parser targets.
     - `_format_hint` defines a function which returns a boolean if the
       Parser can process a particular object

    Eg::

      class ThingParser(TopologyReaderBase):
          format = ['foo', 'bar']

          @staticmethod
          _format_hint(thing):
              try:
                  import WeirdPackage
              except ImportError:
                  return False
              return isinstance(thing, WeirdPackage.Thing)

    This way there is no strict dependency on "WeirdPackage", but if
    a user supplies a WeirdPackage.Thing the "ThingParser' will be able
    to step up and read it.

    .. versionchanged:: 1.0.0
       Added format_hint functionality
    c                    t                               t           |||           	 t          j        |d                   }|D ]9}|                                }| t
          |<   d|v r|d         j        t          |<   :d S # t          $ r Y d S w xY w)Nformat_format_hint)	type__init__r   
asiterableupperr   __func__r   KeyError)clsnamebases	classdictfmtfmt_names         b/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/topology/base.pyr   z_Topologymeta.__init__Q   s    dD%333	/)H"566C    #>>++%("!Y...7&/ "(+   	 	 	DD	s   A< <
B
	B
N)__name__
__module____qualname____doc__r        r   r
   r
   2   s-         <    r    r
   c                       e Zd ZdZd Zd ZdS )TopologyReaderBasea|  Base class for topology readers

    Parameters
    ----------
    filename : str
        name of the topology file
    universe : Universe, optional
        Supply a Universe to the Parser.  This then passes it to the
        atom instances that are created within parsers.

    All topology readers must define a `parse` method which
    returns a Topology object

    Raises
    ------
    * :exc:`IOError` upon failing to read a topology file
    * :exc:`ValueError` upon failing to make sense of the read data

    .. versionadded:: 0.9.0
    .. versionchanged:: 0.9.2
       Added keyword 'universe' to pass to Atom creation.
    c                     || _         d S N)filename)selfr%   s     r   r   zTopologyReaderBase.__init__z   s     r    c                      t          d          )NzOverride this in each subclass)NotImplementedError)r&   kwargss     r   parsezTopologyReaderBase.parse}   s    !"BCCCr    N)r   r   r   r   r   r*   r   r    r   r"   r"   b   sA         .! ! !D D D D Dr    r"   )	metaclassc                 \    t          j        | dd          \  }}||fd|D             fS )a  Squash a child-parent relationship

    Arguments
    ---------
    child_parent_ids - array of ids (unique values that identify the parent)
    *attributes - other arrays that need to follow the sorting of ids

    Returns
    -------
    child_parents_idx - an array of len(child) which points to the index of
                        parent
    parent_ids - len(parent) of the ids
    *parent_attrs - len(parent) of the other attributes
    T)return_indexreturn_inversec                      g | ]
}|         S r   r   ).0attr	sort_masks     r   
<listcomp>zsquash_by.<locals>.<listcomp>   s    $L$L$LT)_$L$L$Lr    )npunique)child_parent_ids
attributesunique_residsatom_idxr2   s       @r   	squash_byr:      sM     *,tD* * *&M9h ]$L$L$L$L$L$L$LLLr    c                     d }t          | d                   t          fdt          j        | dd         |          D                       st	          d           ||  }t          |          dz
  t          j        | d         t                    }fd|D             }t          t          |dd	         |dd                             D ]8\  }\  }}||||<   t          ||          D ]\  }	}
|	||         d         |
|<   9||fS )
a(  Squash per atom data to per residue according to changes in resid

    Parameters
    ----------
    criteria : list of numpy ndarray
      Arrays which when changing indicate a new residue
    to_squash : list of numpy arrays
      Arrays which get squashed according to the criteria arrays

    Returns
    -------
    residx : numpy array
      The Residue *index* that each Atom gets assigned to. [len(resids)]
    squashed : numpy array
      The to_squash arrays reduced down to per Residue values


    Example
    -------
    resids = np.array([2, 2, 3, 3, 2, 2])
    resnames = np.array(['RsA', 'RsA', 'RsB', 'RsB', 'RsC', 'RsC'])
    segids = np.array(['A', 'A', 'A', 'A', 'B', 'B'])

    residx, (new_resids, new_resnames, new_segids) = resid_change_squash(
                                                      (resids,), (resids, resnames, segids))

    # Per atom res index
    residx: [0, 0, 1, 1, 2, 2]
    # Per residue record of each attribute
    new_resids: [2, 3, 2]
    new_resnames: ['RsA', 'RsB', 'RsC']
    new_segids: ['A', 'A', 'B']
    c                      t          j        t          t           j        d | D                                 }dgt	          |d         dz             z   dgz   S )z5Generator of indices to slice arrays when they changec              3   B   K   | ]}|d d         |dd          k    V  d S )N   r   )r0   as     r   	<genexpr>z5change_squash.<locals>.get_borders.<locals>.<genexpr>   s6      "C"Cq1SbS6QqrrU?"C"C"C"C"C"Cr    Nr   r?   )r4   nonzeror   
logical_orlist)arraysborderss     r   get_bordersz"change_squash.<locals>.get_borders   sW    *2="C"CF"C"C"CDD
 
 vWQZ!^,,,v55r    r   c              3   >   K   | ]}t          |          k    V  d S r$   )len)r0   otherl0s     r   rA   z change_squash.<locals>.<genexpr>   s?        "E

b     r    r?   Nz All arrays must be equally sizeddtypec                 F    g | ]}t          j        |j                   S )rL   )r4   zerosrM   )r0   onress     r   r3   z!change_squash.<locals>.<listcomp>   s*    CCCA"(4qw///CCCr    r>   )
rI   all	itertoolschain
ValueErrorr4   
zeros_likeint	enumeratezip)criteria	to_squashrG   rF   residx
new_othersixyoldnewrK   rQ   s              @@r   change_squashrc      se   F6 6 6 
Xa[		B    &/ohqrrlI&N&N     = ;<<< k8$G w<<!D ]8A;c222FCCCCCCCJ s73B3<==>> ! !	6AqqsIz22 	! 	!HC1Xa[CFF	! :r    c                 V    t          |           dk    r| d         S t          |           S )zReturns the value in an array of length 1, or
    the tuple of an array with a longer lengh.

    Parameters
    ----------
    values: array-like
        Array to squash

    Returns
    -------
    values: tuple or single value
    r?   r   )rI   tuple)valuess    r   reduce_singularrg      s+     6{{aayV}}r    )r   	functoolsr   rS   numpyr4   warnings r   r   coordinates.baser   libr   r   r
   r"   r:   rc   rg   r   r    r   <module>rn      s#  .                  & & & & & & & & % % % % % %      - - - - -D - - -`D D D D D= D D D D>M M M,D D DN    r    