B
    d4                 @   s`  d dl mZmZmZ d dlZd dlZd dlZd dlT 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	e_d
d ZG dd deZdd Zdd Zdd Zd9ddZd:ddZG dd deZG dd deZd;d!d"Zd<d#d$Z d=d%d&Z!d>d)d*Z"G d+d, d,eZ#d-d. Z$d?d/d0Z%d1d2 Z&G d3d4 d4eZ'd5d6 Z(d7d8 Z)dS )@    )absolute_importdivisionprint_functionN)*)matrix)flex)rational)range)zipa  
Fits a gaussian function to a list of points.

Parameters
----------
x : scitbx.array_family.flex.double
y : scitbx.array_family.flex.double

Returns
-------
scitbx.math.gaussian_fit_1d_analytical

Examples
--------
>>> from scitbx.array_family import flex
>>> from scitbx.math import gaussian_fit_1d_analytical
>>> x, y = flex.double(), flex.double()
>>> x.append(-1) ; y.append(.1)
>>> x.append(0) ; y.append(1)
>>> x.append(1) ; y.append(.1)
>>> fit = gaussian_fit_1d_analytical(x, y)
>>> print fit.a, fit.b
1.0 2.30258509299
c             C   s   t j| S )N)r   medianZ
dispersion)data r   s/mnt/filia/a/genomebrowser/www/genomebrowser/fleming/tools/molprobity/modules/cctbx_project/scitbx/math/__init__.pymedian_statistics)   s    r   c               @   s$   e Zd Zdd Zdd Zdd ZdS )line_given_pointsc             C   s:   dd |D | _ | j d | j d  | _t| j | _d S )Nc             S   s   g | ]}t |qS r   )r   col).0pointr   r   r   
<listcomp>/   s    z.line_given_points.__init__.<locals>.<listcomp>   r   )pointsdeltafloatnorm_sqdelta_norm_sq)selfr   r   r   r   __init__.   s    zline_given_points.__init__c             C   s<   | j dkr|| jd   S | j|| jd   | j  S )zAhttp://mathworld.wolfram.com/Point-LineDistance3-Dimensional.htmlr   )r   r   r   r   cross)r   r   r   r   r   distance_sq3   s    
zline_given_points.distance_sqc             C   s6   | j d | | j | j  }| j d | j|  S )Nr   )r   dotr   r   )r   r   tr   r   r   perp_xyz:   s    "zline_given_points.perp_xyzN)__name__
__module____qualname__r   r   r!   r   r   r   r   r   ,   s   r   c             C   s,   t t| d | d  | d  d d ddS )Nr         g      ?g       @g      )maxmin)rr   r   r   *r3_rotation_cos_rotation_angle_from_matrix>   s    $r*   c             C   sB   t | }|dk r*t|}|t| }nd}d| | |    S )z
  Chirikjian, G. Stochastic models, information theory, and Lie groups.
  Volume 2, pp 39-40.
  Applied and Numerical Harmonic Analysis, Birkhauser
  g      ?g      ?)r*   mathacossin	transpose)r)   Z	cos_thetathetaZa1r   r   r   r3_rotation_matrix_logarithmE   s    
r0   c                 s<   | st dddl ttj fdd| D }t| S )z
  Calculates an approximation of the Riemannian (geometric) mean through
  quaternion averaging

  Arithmetic and geometric solutions for average rigid-body rotation (2010).
  I Sharf, A Wolf & M.B. Rubin, Mechanism and Machine Theory, 45, 1239-1251
  zAverage of empty sequencer   Nc                s   g | ]} j t|qS r   )r   r   %r3_rotation_matrix_as_unit_quaternion)r   e)scitbxr   r   r   g   s   zEr3_rotation_average_rotation_matrix_from_matrices.<locals>.<listcomp>)	TypeErrorZscitbx.matrix	functoolsreduceoperatoraddZ%r3_rotation_unit_quaternion_as_matrix	normalize)matricesaverager   )r3   r   1r3_rotation_average_rotation_matrix_from_matricesW   s    	

r<   d   -C6?c                s   | st d|dk s|dkr$tdddlm || }dt|  }| d }xVt|D ]J}|  |tt	j
 fdd| D  }| |k r|S || 9 }qVW tdd	S )
a,  
  Calculates an approximation of the Riemannian (geometric) mean by iteratively
  averaging the rotation matrix logarithms

  Nonparametric Second-order Theory of Error Propagation on Motion Groups (2008).
  Y. Wang & G. S. Chirikjian, The International Journal of Robotics Research 27, 1258-1273
  zAverage of empty sequencer   zInvalid iteration parameters)so3_lie_algebrag      ?c                s   g | ]}j j | d qS ))r   )elementZfrom_rotation_matrix)r   m)inverser?   r   r   r      s   z@r3_rotation_average_rotation_via_lie_algebra.<locals>.<listcomp>zIteration limit exceededN)r4   
ValueErrorscitbx.mathr?   lenr	   rB   r5   r6   r7   r8   r   ZexponentialRuntimeError)r:   maxiterZconvergenceZconv_sqZnormcurrentiZlog_diffr   )rB   r?   r   ,r3_rotation_average_rotation_via_lie_algebram   s$    	rJ   Fc             C   s  |rdd | D } dd | D }dd | D }t |d |d  |d  |d |d   |d  |d  |d  |d |d   |d |d  |d |d  |d  |d |d   |d  |d  |d  |d |d   |d |d  |d  |d  |d |d  |d f	S )Nc             S   s   g | ]}|t j d  qS )   )r+   pi)r   ar   r   r   r      s    z*euler_angles_as_matrix.<locals>.<listcomp>c             S   s   g | ]}t |qS r   )r+   cos)r   rM   r   r   r   r      s    c             S   s   g | ]}t |qS r   )r+   r-   )r   rM   r   r   r   r      s    r   r      )r   sqr)anglesdegcsr   r   r   euler_angles_as_matrix   s    &(&(rU   c               @   s   e Zd ZdddZdd ZdS )erf_verification绽|=c             C   s   || _ d| _d S )Nr   )	tolerance	max_delta)r   rX   r   r   r   r      s    zerf_verification.__init__c             C   s   ||}t |t |krt | d}t | d}t|t|ksPtt|dkrp|d |d kspttt|d t|d  }| j|k r|| _|| jkrt	|||| d S )Nr2   rO   r   r   )
strlowersplitrE   AssertionErrorabsr   rY   rX   print)r   fxZexpected_resultresultmeZmexr   r   r   r   __call__   s    

zerf_verification.__call__N)rW   )r"   r#   r$   r   rd   r   r   r   r   rV      s   
rV   c               @   s.   e Zd ZdddZdd Zdd	 Zd
d ZdS )minimum_covering_sphere_ndNr   r   r   r   c                s  t |dks|dkst|d kr$d}d| _t |dkrF|| _|| _d S t |dkrjt|d | _|| _d S t |d j}dt |  t fddt	t |D }xt
dg| x$t|j|D ]\ } | 7 qW t
fdd|D }d}	x,t|j|jD ]\ }
|	 |
d  7 }	q
W t|	}	| }||	 || k rNP g }x*t|j|jD ]\ }
| |
  qbW t
|}| }|dkst|| }|  jd7  _qW j| _|| _d S )	Nr   gư>r   g      ?c                s   g | ]} qS r   r   )r   rI   )wr   r   r      s    z7minimum_covering_sphere_nd.__init__.<locals>.<listcomp>c                s   g | ]}t  | qS r   )r^   )r   r    )ra   r   r   r      s    rO   )rE   r]   _n_iterations_center_radiustupleelemsr   rowr	   r   r
   r+   sqrtr'   appendsum)r   r   epsilonradius_if_one_or_no_pointscenter_if_no_pointsZn_dimweightsr    Zradiisigmar)   tauZw_rZsum_w_rr   )rg   ra   r   r      sJ      

z#minimum_covering_sphere_nd.__init__c             C   s   | j S )N)rh   )r   r   r   r   n_iterations   s    z'minimum_covering_sphere_nd.n_iterationsc             C   s   | j S )N)ri   )r   r   r   r   center   s    z!minimum_covering_sphere_nd.centerc             C   s   | j S )N)rj   )r   r   r   r   radius   s    z!minimum_covering_sphere_nd.radius)Nr   rf   )r"   r#   r$   r   rw   rx   ry   r   r   r   r   re      s     
&re   r   r   r   r   c             C   s2   |d krd}t | tjrt}nt}|| |||dS )Ngư>)r   rq   rr   rs   )
isinstancer   vec3_doubleZminimum_covering_sphere_3dre   )r   rq   rr   rs   implr   r   r   minimum_covering_sphere   s     r~   c             C   s(   |d k	r|  dkstt| |||S )Nr   )ndr]   ext!row_echelon_back_substitution_int)row_echelon_formvsolutionZindependent_flagsr   r   r   r      s    r   c             C   s2   |d k	st |d k	r$| dks$t t| ||S )Nr   )r]   r   r   #row_echelon_back_substitution_float)r   r   r   r   r   r   r     s
    r   -q=
   c             C   sZ  t | tjr|  } t |tjr:| dks0tt|}|dkrHd}n t| 	 tt
|  | }t||}|| }|  }| }t|||d}	|	jdkr|	jt|	j|d}
n|  st|  }tjj|}| }| }|||}||}|	j}t|||d}	|	j|ks*t|	jt|	jd|d}
|
dk	rV||
}
|
S )a  Assumes a is symmetric, without checking to avoid overhead.

Special case of
  generalized_inverse(a) * b
taking advantage of the fact that a is real and symmetric.

Opportunistic algorithm: first assumes that a has full rank. If this
is true, solves a*x=b for x using simple back-substitution.

Only if a is rank-deficient:
  To obtain the x with minimum norm, transforms a to a basis formed
  by its eigenvectors, solves a*x=b in this basis, then transforms
  x back to the original basis system.

Returns None if a*x=b has no solution.
r   Nr   )a_workb_workmin_abs_pivot)Zfree_valuesrq   )r   r   max_rank)r{   r   recas_flex_double_matrix	n_columnsr]   r   doubler'   allr^   	deep_copyZrow_echelon_full_pivotingZnullityZback_substitutionZis_square_matrixr3   linalgeigensystemreal_symmetricvectorsZmatrix_transposeZmatrix_multiplyZrank)rM   bZrelative_min_abs_pivotZabsolute_min_abs_pivotZ back_substitution_epsilon_factorr   rq   ZawZbwZefra   esrS   Zctr   r   r   r   )solve_a_x_eq_b_min_norm_given_a_sym_b_col  s@    
 




r   c               @   s    e Zd ZdZdd Zdd ZdS )finite_difference_computationa   Computing the derivative of a scalar function f(x, ...) wrt x,
  where x may be a vector, involves computing f(x + h, ...)
  where h is suitably chosen a delta. So as to keep numerical accuracy, it
  is best to follow a well known recipe to choose h knowing its
  direction. When using that value, a finite difference computation typically
  reaches a precision of self.precision

  Reference: chap 5.7 of Numerical Recipes in C
  c             C   s    t tj jj}t || _d S )N)r+   rn   r3   Zdouble_numeric_limitsrq   	precision)r   r2   r   r   r   r   W  s    z&finite_difference_computation.__init__c             C   s0   || j  }}|t| }|| }|| | }|S )z Compute the value h in the given direction that is most suitable
    for use in finite difference computation around the given point x.
    The vector 'direction' may not be a unit-vector.
    )r   r^   )r   r   	directionra   rT   uhr   r   r   
best_delta[  s
    z(finite_difference_computation.best_deltaN)r"   r#   r$   __doc__r   r   r   r   r   r   r   L  s   	r   c             C   s~   t j}t j}|t j d }|t j d }|d | || ||  }|d | || ||  }	|d | ||  }
||	|
fS )zj
  Returns a point on sphere of radius r: see definition of polar (sperical)
  coordinate system in 3D.
  rK   r   r   rO   )r+   r-   rN   rL   )r)   Zs_degZt_degrx   r-   rN   rT   r    ra   yzr   r   r   point_on_spheref  s    r   c       
      C   s   ||g d dkst|d | d  |d | d  |d | d  g}t|g}|d k	rf|dkstnF|dksrtt|d d |d d  |d d  }t|| d }|dt|d   }t }x&t|d D ]}	|	||	 |   qW |
| |S )Nr   r   rO   )countr]   r   r|   r+   rn   intr   r	   extendro   )
startendnstepZvecr)   Z
vec_lengthZdrr   rI   r   r   r   equally_spaced_points_on_vectort  s    .*
r   c             C   s.  yt | }W n tk
r*   t| }Y nX t|}|d rn||d  }|d|d d  }||d d }n@||d  ||d d   d }|d|d  }||d d }t|}|d r||d  }||d  }n@||d  ||d d   d }||d  ||d d   d }|d ||||d fS )z
  Returns the Tukey five number summary (min, lower hinge, median, upper hinge,
  max) for a sequence of observations. This function gives the same results
  as R's fivenum function.
  rO   Nr   r   )r   sortedAttributeErrorrE   )r   Zsortsr   Zmedr[   upperZlhingeZuhinger   r   r   five_number_summary  s&       r   c               @   s   e Zd ZdZdd ZdS )sin_cos_tablez8
  Always evaludate performance when it is important!
  c             C   st   || _ dtj | j  | _t | _t | _xBt| j D ]4}| j	t
|| j  | j	t|| j  q8W d S )NrO   )r   r+   rL   r   r   r   Z	sin_tableZ	cos_tabler	   ro   r-   rN   )r   r   rI   r   r   r   r     s    

zsin_cos_table.__init__N)r"   r#   r$   r   r   r   r   r   r   r     s   r   c       
      C   s   g }xZt | D ]N\}}g }x.t | D ]"\}}t|| |k r$|| q$W ||kr|| qW | dd }x*t |D ]\}}x|D ]}	|||	< qW qvW |S )aB  
  Best explained by examples:
    for array [0.232, 0.002, 0.45, 1.2, 0.233, 1.2, 0.5, 0.231, 0,0,0,0,0]
    return    [0,     1,     2,    3,   0,     3,   4,   0,     1,1,1,1,1]
    if eps=0.01.
  Other examples:
    [0, 2, 0, 2]
    [0, 1, 0, 1]

    [0, 0, 0, 0]
    [0, 0, 0, 0]

    [1, 2, 3, 4]
    [0, 1, 2, 3]
  N)	enumerater^   ro   )
ra   epsZii_allrI   ZxiiijZxjr   Ziiir   r   r   similarity_indices  s      
 r   c             C   s   |d dkrt d| || | }| || | }xRtd|dD ]B}|d dkrl|d| |||   7 }qB|d| |||   7 }qBW || d S )z<
  Integral of f on [a,b] using composite Simpson's rule.
  rO   r   zn must be evenr   r%      )rC   r	   )r`   rM   r   r   r   rT   rI   r   r   r   simpson  s      r   )r=   r>   )F)Nr   rz   )NNN)NN)r   r   r   )NN)*
__future__r   r   r   r5   r+   r7   Zscitbx.math.extZscitbx.linalg.eigensystemr3   Zscitbx.math.gaussianr   scitbx.array_familyr   boost_adaptbx.boostr   	six.movesr	   r
   Zgaussian_fit_1d_analyticalr   r   objectr   r*   r0   r<   rJ   rU   rV   re   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sN   
$
7  
  
 
	  
8
