B
    d                 @   s   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
 dd Zd.dd	Zd/ddZdd Zdd Zdd Zdd Zdd Zdd ZG dd deZdd Zdd Zd d! Zd0d"d#Zd1d$d%Zd2d'd(Zd3d)d*Zd4d,d-ZdS )5    )absolute_importdivisionprint_function)objectN)matrix)rangec             C   s   | |k| |k  S )zT
  cmp(x, y) -> integer

  Return negative if x<y, zero if x==y, positive if x>y.
   )xyr   r   p/mnt/filia/a/genomebrowser/www/genomebrowser/fleming/tools/molprobity/modules/cctbx_project/libtbx/math_utils.pycmp   s    r   c             C   sH   d| }| dkr*t t| | d | S t t| | d | S dS )a  
  Python 3 defaults to rounding to the nearest even number (round half to even),
  so this function keeps the Python 2 behavior, which is rounding half away
  from zero.

  References:
  https://docs.python.org/3.7/library/functions.html#round
  https://en.wikipedia.org/wiki/Rounding#Round_half_to_even

  https://docs.python.org/2.7/library/functions.html#round
  https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero

  Function from:
  http://python3porting.com/differences.html#rounding-behavior
  
   r   g      ?N)floatmathfloorceil)r	   dpr   r   r   round2   s    r      Fc             C   s  t | tr~t| rtdS t| td| k sDt| td| krtdd|  }|d| 7 }||  }|rl|S t|S t| |S t | trx"t| D ]\}}t||| |< qW t | t	rt| } x"t| D ]\}}t||| |< qW t	| } t | t
jr0t| } x$t| D ]\}}t||| |< q
W t
| } t | t
jr| j}t| } x$t| D ]\}}t||| |< qVW t
j| |d} | S )a{  
  round off all floats in a list (or tuple) of list (or tuples)
  recursively using round2() defined above as in:
  >>> math_utils.roundoff( [12.3454, 7.4843, ["foo", (35.3581, -0.3856, [4.2769, 3.2147] )] ])
  [12.345, 7.484, ['foo', (35.358, -0.386, [4.277, 3.215])]]
  If value is less than 10**-precision or greater than 10**precision then return with scientific notation
  nanz1e-%dz9e%d%z%dz.%de)Zelemsn)
isinstancer   r   isnanabsr   list	enumerateroundofftupler   ZsqrZrecr   )val	precisionZ	as_stringZfstrZval2strivZvalnr   r   r   r   %   s>    

(



r   c             C   s    | dk rt | d S t | d S )Nr   g      ?)int)r	   r   r   r   iroundM   s     r%   c             C   s   t t| S )N)r%   r   r   )r	   r   r   r   iceilQ   s    r&   c             C   s   t t| S )N)r%   r   r   )r	   r   r   r   ifloorT   s    r'   c             C   s   t | d S )Ng      ?)r'   )r	   r   r   r   nearest_integerW   s    r(   c             C   s
   |  p|S )z2 does p => q in the sense of logical implication? r   )r   qr   r   r   
does_implyZ   s    r*   c             C   s   t | |ot || S )z3 does p <=> q in the sense of logical equivalence? )r*   )r   r)   r   r   r   are_equivalent^   s    r+   c               @   s&   e Zd Zd	ddZdd Zdd ZdS )
nested_loopNTc             C   s   |d krdgt | }nt |t |ks,t|s^t|}x$tt |D ]}||  d7  < qFW x(tt |D ]}|| || ksltqlW || _|| _t|| _x8tt |D ](}|| || kr| jd  d8  < P qW d S )Nr      )lenAssertionErrorr   r   beginendcurrent)Or2   r1   Z
open_ranger"   r   r   r   __init__d   s     
znested_loop.__init__c             C   s   | S )Nr   )r4   r   r   r   __iter__w   s    znested_loop.__iter__c             C   sh   | j }| j}| j}t|}xD|dkr^|d8 }||  d7  < || || k rP|S || ||< qW td S )Nr   r-   )r1   r2   r3   r/   StopIteration)r4   becr"   r   r   r   __next__z   s    
 znested_loop.__next__)NT)__name__
__module____qualname__r5   r6   r;   r   r   r   r   r,   b   s   
r,   c             C   s   t | dkrdS t | d }x|}|d8 }| | | | k rt | }x|d8 }| | | | k rDP qDW | | | |  | |< | |< | |d }| |d= |  | | dS |dkr|   dS qW dS )aF  Emulation of C++ std::next_permutation:
  Treats all permutations of seq as a set of "dictionary" sorted
  sequences. Permutes the current sequence into the next one of this set.
  Returns true if there are more sequences to generate. If the sequence
  is the largest of the set, the smallest is generated and false returned.
r-   FNTr   )r/   reverseextend)seqr"   Ziijtailr   r   r   next_permutation   s*     

rD   c             C   sJ   dd l }t| }x4t|D ](}||}| | | |  | |< | |< qW d S )Nr   )randomr/   r   	randrange)r   rE   r   r"   rB   r   r   r   random_permutation_in_place   s
    
rG   c             C   sF   g }d}x8| dkr@x"| | dkr4| | | | } qW |d7 }q
W |S )z<http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata   r-   r   )append)r   result	candidater   r   r   prime_factors_of   s    

rL   c             C   sL   |r
d}n
dt j }t | |} | dk r0| |7 } |rH| |d krH| |8 } | S )Nih  rH   r   )r   pifmod)ZphiZdegZzero_centeredZperiodr   r   r   normalize_angle   s     
 rO   c             C   s   t | d|dS )zW Return median value which is same as percentile_based_spread with
    cutoff of 0.5
  g      ?)pbs_fractionsort)percentile_based_spread)valuesrQ   r   r   r   median   s    rT   ~jt?c             C   sV   |dkr6t | dr|  }nt| }|dk r2d}nd}|rFt| |dS t| |dS dS )z
  See Pozharski (2010) Acta. Cryst. D66, 970-978.  The default value of the
  pbs_fraction parameter is for 3D geometries, and should be adjusted as
  circumstances dictate.
  Nsizei TF)rP   )hasattrrV   r/   !percentile_based_spread_with_sort&percentile_based_spread_with_selection)rS   rP   rQ   r   r   r   r   rR      s    

rR   c             C   s   t | } t| }|dkrdS |dkr,| d S tt|| |d }t|| }||kr^| | S | | }| | }|| }|| }||kst|| ||  }	||	||   }
|
S )z
  See Pozharski (2010) Acta. Cryst. D66, 970-978.  The default value of the
  pbs_fraction parameter is for 3D geometries, and should be adjusted as
  circumstances dictate.
  r   r-   )sortedr/   minr&   r'   r0   )rS   rP   r   Zi_highZi_lowZx_highZx_lowZ	frac_highZfrac_lowZ
frac_deltaZx_fracr   r   r   rX      s$      rX   -C6?c             C   s   ddl m} || } |  }|j}|j}|  }|}d}	xlt|D ]`}
|| |k rVP |	rhd||  }nd||  }| |k d|   }||k }	|}|	r|}qD|}qDW |S )a  
  See Pozharski (2010) Acta. Cryst. D66, 970-978.  The default value of the
  pbs_fraction parameter is for 3D geometries, and should be adjusted as
  circumstances dictate.
  This version uses selection to get the pbs within tolerance of true value
   if possible
  r   )flexTg      ?)	Zscitbx.array_familyr]   ZdoubleZmin_max_meanr[   maxrV   r   count)rS   rP   	tolerancer]   ZmmmZlowZhighZ	max_tries
last_valueZtoo_lowr"   ZworkingZfracr   r   r   rY      s*    	
rY   )r   )r   F)FF)N)rU   N)rU   )rU   r\   )
__future__r   r   r   builtinsr   r   Zscitbxr   	six.movesr   r   r   r   r%   r&   r'   r(   r*   r+   r,   rD   rG   rL   rO   rT   rR   rX   rY   r   r   r   r   <module>   s.   

($
	


 