3
h}\XH                 @   s|   d 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
 dZG dd deZedZG dd	 d	eZG dd
 d
eZdS )z'
Arrays indexed by alphabetic strings.
    N   )Alphabet)unambiguous_dna_alphabetunambiguous_rna_alphabetunambiguous_protein_alphabet)isintischarAlphabeticArraysubmatrix_alphabet	SubMatrixMotifc               @   sZ   e Zd ZdZddgZdddZdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd ZdS )r	   a'  An alphabetic array. Wraps a numpy array so that each dimension
    can be associated with an alphabet and indexed with characters or strings.

    Attributes :
    - alphabets -- A sequence of alphabets used to index the array
    - array     -- The underlying array object that is indexed.

    Examples :

    >>> from weblogo.seq import *
    >>> from weblogo.matrix import AlphabeticArray
    >>>
    >>> str(protein_alphabet)
    'ACDEFGHIKLMNOPQRSTUVWYBJZX*-'
    >>> matrix = AlphabeticArray( (protein_alphabet, protein_alphabet) )
    >>>
    >>> # Index by character or integer:
    >>> matrix['A', 'C'] = 10
    >>> matrix[0,1]
    10
    >>>
    >>> # Different alphabets on each dimension:
    >>> import numpy as na
    >>> a234 = zeros( shape = (2,3,4) )
    >>> alpha = ( "AB", "ABC", "ABCD")
    >>> aa = AlphabeticArray(alpha,a234)
    >>> aa['A', 'B', 'C'] = 22
    >>>
    >>> # String indices are converted to integer index arrays:
    ...
    >>> aa['A', 'B', 'ABCD']
    array([ 0,  0, 22,  0])


    Authors:
    o GEC 2005, JXG 2006

    	alphabetsarrayNc             C   s$  G dd dt }g }g }xz|D ]r}t|tr4t|}|dkrT|jd |j|  qt|trx|jt| |j| q|jt| |jd qW t|}|dkrtj	||d}n\tj
||d}|j}t|t|krtdx.t||D ] \}	}
|	dk	r|	|
krtdqW || _t|| _dS )a  
        Args:
        - alphabets -- a list of alphabets (as string or Alphabet objects) to
                    be used to convert strings into indices. The lengths of
                    the alphabets match the shape of the indexed array.
                    Alternatively, an integer or None in the list indicate a
                    non-alphabetic dimension. If None the dimension length is
                    taken from values argument.
        - values -- An array of values to be indexed. If None a new
                 array is created. If this argument is not a numpy array
                 then the alphabet list must be explicit (cannot contain
                 None.)
        - dtype -- An optional numpy type code.
        c               @   s   e Zd Zdd Zdd ZdS )z.AlphabeticArray.__init__.<locals>.NullAlphabetc             S   s   t dd S )Nz(This dimension does not have an alphabet)
IndexError)selfkey r   @/home/birch/.local/lib/python3.6/site-packages/weblogo/matrix.pyordh   s    z2AlphabeticArray.__init__.<locals>.NullAlphabet.ordc             S   s   t dd S )Nz(This dimension does not have an alphabet)r   )r   r   r   r   r   ordsk   s    z3AlphabeticArray.__init__.<locals>.NullAlphabet.ordsN)__name__
__module____qualname__r   r   r   r   r   r   NullAlphabetg   s   r   N)shapedtype)r   z$The values array is the wrong shape.)object
isinstancestrr   appendleninttuplenpzerosasarrayr   
ValueErrorzipr   r   )r   r   valuesr   r   alphar   aZvshapes1s2r   r   r   __init__T   s4    



zAlphabeticArray.__init__c             C   s   | j j| j|S )N)r   __getitem___ordkey)r   r   r   r   r   r.      s    zAlphabeticArray.__getitem__c             C   s   | j j| j|| d S )N)r   __setitem__r/   )r   r   valuer   r   r   r0      s    zAlphabeticArray.__setitem__c                sH    fdd t |tr4t fddt|| jD S  || jd S dS )zConvert string indices into integers. Handles characters, strings
        slices with strings, and tuples of the same. Anything else is
        unchanged.
        c                s   | d krd S t | ts t | tr^t| } t| dkr>|j| S t| dkrNd S tj|j| S t | tr | j	|} | j
|}| j}t|||S | S d S )Nr   r   )r   r   r   r    r   r#   r%   r   slicestartstopstep)r   r)   r3   r4   r5   )normr   r   r6      s    

z%AlphabeticArray._ordkey.<locals>.normc                s   g | ]\}} ||qS r   r   ).0kr*   )r6   r   r   
<listcomp>   s    z+AlphabeticArray._ordkey.<locals>.<listcomp>r   N)r   r"   r'   r   )r   r   r   )r6   r   r/      s    
zAlphabeticArray._ordkeyc             C   s   | j |}g }xnt|D ]b\}}|dkr:td| jj| }tj|}x*tt|| d D ]}|dtjf }qZW |j	| qW | jj
t|S )z Return an array of shape (len(key1), len(key2), ...) whose values
        are indexed by keys.

        a.outerindex( (I,J,K) )[i,j,k] == a.array[I[i],J[j],K[k]]

        Nr   r   .)r/   	enumerateranger   r   r#   r%   r    Znewaxisr   r.   r"   )r   keysZ	outerkeysir8   jr   r   r   index   s    	

zAlphabeticArray.indexc             C   s   | j |}t||S )zCreate a new AlphabeticArray with the given alphabet. The new
        alphabet must be a subset of the current alphabet. Useful for
        extracting a submatrix or for permuting the alphabet.
        )r?   r	   )r   Znew_alphabetZ	new_arrayr   r   r   reindex   s    
zAlphabeticArray.reindexc             C   s.   yt j| |S  tk
r(   t| j|S X d S )N)r   __getattr__AttributeErrorgetattrr   )r   namer   r   r   rA      s    zAlphabeticArray.__getattr__c             C   s2   yt j| ||S  tk
r,   t| j||S X d S )N)r   __setattr__rB   setattrr   )r   rD   r1   r   r   r   rE      s    zAlphabeticArray.__setattr__)NN)r   r   r   __doc__	__slots__r-   r.   r0   r/   r?   r@   rA   rE   r   r   r   r   r	   (   s   &
8ZARNDCQEGHILKMFPSTWYVBZXc               @   sD   e Zd ZdZdddddgZddd	Zd
d Zedej	fddZ
dS )r   aV  A two dimensional array indexed by an Alphabet. Used to hold substitution
    matrices and similar information.

    Various standard substitution matrices are available from the data package
    >>> from weblogo import data
    >>> mat = SubMatrix.read(data.data_stream('blosum100'))

    Attr:
    - alphabet     -- An Alphabet
    - array        -- A numpy array
    - name         -- The name of this matrix (if any) as a string.
    - description  -- The description, if any.
    - scale        -- The scale constant of a log-odds matrix, if known.

    Authors:
    o GEC 2005, JXG 2006

    alphabetr   rD   descriptionscaleNc             C   s4   t j| ||f|| t|| _|| _|| _|| _d S )N)r	   r-   r   rI   rD   rJ   rK   )r   rI   r   typeofrD   rJ   rK   r   r   r   r-      s
    
zSubMatrix.__init__c             C   s   t j| ||fS )N)r	   r@   )r   rI   r   r   r   r@     s    zSubMatrix.reindexc       
      C   s  |dkrt }t|}tj||f|}d}xt| D ] \}}|j s4|d dks4|d dkr`q4|j }|d |d krzq4|d j r|d || krtdj	||d || |d j r|dd }t|dkr|dd }t||krtd	j	|x(t
d|D ]}	t||	 |||	f< qW |d7 }||kr4P q4W td
xTt
d|D ]F}x>t
d|D ]0}	|||	f ||	|f kr^tdj	||	q^W qNW t||S )a]   Parse and return a substitution matrix

        Arguments:
        - fin       --  matrix file
        - alphabet  -- The set of substitution characters. Default: ''
        -  typeof    -- A numpy type or typecode.
        Returns:
        -  A numpy matrix of substitution scores
        Raises:
        -  ValueError on unreadable input
        Nr   #*r   z(Incompatible alphabet: line {} : {} {}:       z$SubMatrix matrix parseerror: line {}zPremature EOFz+Substitution matrix is asymmetric! ({}, {}))r
   r    r#   r$   r:   isspacesplitisalphar&   formatr;   floatr   )
finrI   rL   Lmatrixr=   Zlinenumlinecellsr>   r   r   r   read  sB     zSubMatrix.read)NNNNN)r   r   r   rG   rH   r-   r@   staticmethodr#   float64r[   r   r   r   r   r      s    
c               @   s\   e Zd ZdZddgZdddZedd Zd	d
 Zdd Z	dd Z
dd ZedddZdS )r   aV  A two dimensional array where the second dimension is indexed by an
    Alphabet. Used to represent sequence motifs and similar information.


    Attr:
    - alphabet     -- An Alphabet
    - array        -- A numpy array
    - name         -- The name of this motif (if any) as a string.
    - description  -- The description, if any.

    ZXXz//Nc             C   s*   t j| d |f|| || _|| _|| _d S )N)r	   r-   rD   rJ   rK   )r   rI   r   r   rD   rJ   rK   r   r   r   r-   h  s    zMotif.__init__c             C   s
   | j d S )Nr   )r   )r   r   r   r   rI   o  s    zMotif.alphabetc             C   s   t |tj| d |fS )N)r   r	   r@   )r   rI   r   r   r   r@   s  s    zMotif.reindexc             C   s   | j ddd | _ dS )zReverse sequence dataNr   )r   )r   r   r   r   reverse{  s    zMotif.reversec             C   sR   ddl m}m} | j}||||j }d|f| _| j|}d|f| _|j| _dS )z!Complement nucleic acid sequence.r   )Seqr   N)Zweblogo.seqr`   r   rI   
complementr   r@   r   )r   r`   r   rI   Zcomplement_alphabetmr   r   r   ra     s    


zMotif.complementc             C   s   | j   | j  dS )zkComplements and reverses nucleic acid
         sequence (i.e. the other strand of a DNA sequence.)
        N)r_   ra   )r   r   r   r   reverse_complement  s    zMotif.reverse_complementc             C   sv  g }d}xf|D ]^}|j  s|d dkr(q|j }|d dksH|d dkrLd}|r|d | jkrbP q|j| qW t|dk rtd|jd}t|}t|}	t|d }
|d dkp|d dkp||
d	 kp||
d kstd
t|d }
x8td	t|D ]&}|
t|| k rtdj| qW |d dksD|d dkrN|jd d}x4|D ],}t	|sttdj|t
|sXd}qXW |rdnd}|rxt|D ]N\}}t
|d  r|d d dkrtdj||jd dj|}qW nfg }xVt|D ]J\}}t	|d  r@|d d dkr@tdj||j|jd qW dj|}t|}|rt|}|j|s|}n6tttf}x |D ]}|j|r|}P qW |s|}t|d t|d	 krx|D ]}|j  qW t|}	t|d }
tj|	|
ftjd}x>t|	D ]2}x*t|
D ]}t|| | |||f< q0W q"W |rf|j  t||j|S )z Parse a TRANSFAC-format PWM from a file.
        Returns a Motif object, representing the provided
        PWM along with an inferred or provided alphabet.
        Fr   rM   ZPOZP0T   zVacuous file.r   zMissing header line!zInconsistant length, row: {}zEExpected a single character per header item, but got "{}" as one itemPz*Expected position as first item on line {} )r   )rQ   rR   _TRANSFAC_DELIM_LINESr   r    r&   popr;   rT   r   r   r:   joinr   Z
alphabeticr   r   r   r#   r$   r]   rU   Z	transposer   r@   )clsrV   rI   itemsr3   rY   stuffheaderZhcolsZrowscolsr=   Zposition_headerhZalphabet_headerrZdefacto_alphabetr*   r   rX   cr   r   r   read_transfac  s    






"
"


$zMotif.read_transfac)NNNNN)N)r   r   r   rG   rg   r-   propertyrI   r@   r_   ra   rc   classmethodrr   r   r   r   r   r   Y  s    
)r	   r
   r   r   )rG   numpyr#   seqr   r   r   r   utilsr   r   __all__r   r	   r
   r   r   r   r   r   r   <module>   s    7x