B
    §d;— ã               @   s‚  d dl mZmZ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
 d dlZd dlmZ d d	lmZ d d
lmZ d dlZd dlmZ d dl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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 d dlm%Z& d dlm'Z' d dl(m)Z) d dl(m*Z* G dd„ de+ƒZ,G dd„ de	j-ƒZ.G dd„ de+ƒZ/G dd„ de+ƒZ0dS )é    )Úabsolute_importÚdivisionÚprint_function)Úext)Ústructure_factors)Úmiller)Úcrystal)ÚsgtbxN)Úadptbx)Úeltbx)Úflex)Úmatrix)Úcount)Ú	count_maxÚSorryÚKeep)Úapprox_equal)Ú
group_args)Ú	is_string)Úneutron_news_1992_table)Ú&format_float_with_standard_uncertainty)Ú
covariance)Úrange)Úzipc               @   s   e Zd Zddd„ZdS )Úscattering_type_registry_paramsNc             C   s   || _ || _|| _|| _d S )N)Úcustom_dictÚd_minÚtableÚ'types_without_a_scattering_contribution)Úselfr   r   r   r   © r    ús/mnt/filia/a/genomebrowser/www/genomebrowser/fleming/tools/molprobity/modules/cctbx_project/cctbx/xray/structure.pyÚ__init__    s    z(scattering_type_registry_params.__init__)NNNN)Ú__name__Ú
__module__Ú__qualname__r"   r    r    r    r!   r      s      r   c               @   sr  e Zd ZdZd;dd„Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Z	e
e
e
e
e
fdd„Zdd„ Zdd„ Zd<dd„Zd=dd„Zdd„ Zd>dd„Zd?dd„Zd d!„ Zd@d"d#„Zd$d%„ ZdAd'd(„ZdBd)d*„ZdCd+d,„ZdDd-d.„ZdEd/d0„ZdFd1d2„ZdGd6d7„ZdHd8d9„Zd:d;„ ZdId<d=„ZdJd>d?„Z dKd@dA„Z!dLdBdC„Z"dMdDdE„Z#dNdFdG„Z$dOdHdI„Z%dJdK„ Z&dLdM„ Z'dNdO„ Z(dPdQ„ Z)dRdS„ Z*dPdTdU„Z+dQdVdW„Z,dRdXdY„Z-dZd[„ Z.d\d]„ Z/d^d_„ Z0d`da„ Z1dbdc„ Z2ddde„ Z3dfdg„ Z4dhdi„ Z5djdk„ Z6dldm„ Z7dndo„ Z8dpdq„ Z9drds„ Z:dtdu„ Z;dvdw„ Z<dxdy„ Z=dSdzd{„Z>d|d}d~dgddfd€d„Z?d|d}d~dgddfd‚dƒ„Z@d|d}d~dd„gddfd…d†„ZAd|d~dgddfd‡dˆ„ZBd‰dŠ„ ZCd‹dŒ„ ZDddŽ„ ZEdd„ ZFdTd’d“„ZGd”d•„ ZHdUd–d—„ZIdVd˜d™„ZJdWd›dœ„ZKddž„ ZLdŸd „ ZMdXd¡d¢„ZNdYd£d¤„ZOdZd¦d§„ZPd¨d©„ ZQdªd«„ ZRd[d¬d­„ZSd®d¯„ ZTd\d°d±„ZUd]d²d³„ZVd´dµ„ ZWd¶d·„ ZXd¸d¹„ ZYd^d»d¼„ZZd_d½d¾„Z[d`d¿dÀ„Z\dadÁdÂ„Z]dbdÃdÄ„Z^dcdÅdÆ„Z_dddÈdÉ„Z`dedÊdË„ZadÇeb cdÌ¡dÍfdÎdÏ„ZddfdÐdÑ„ZedgdÒdÓ„ZfdÔdÕ„ ZgdÖd×„ ZhdØdÙ„ ZidÚdÛ„ ZjdÜdÝ„ ZkdÞdß„ Zldàdá„ Zmdhdâdã„Zndädå„ Zodædç„ Zpdidèdé„Zqdjdëdì„Zrdkdîdï„Zsdðdñ„ Ztdòdó„ Zudldôdõ„Zvdmdöd÷„Zwdndødù„Zxdodúdû„Zydüdý„ Zzdþdÿ„ Z{dpd d„Z|dd„ Z}dd„ Z~dd„ Zdd	„ Z€d
d„ Zdqdd„Z‚drdd„Zƒdsdd„Z„dtdd„Z…dudd„Z†dvdd„Z‡dwdd„Zˆdd„ Z‰dd „ ZŠd!d"„ Z‹dxd#d$„ZŒd%d&„ Zd'd(„ ZŽdyd+d,„Zdzd-d.„Zdg dddfd/d0„Z‘e’d1d2„ ƒZ“e’d{d3d4„ƒZ”d|d5d6„Z•d7d8„ Z–d9d:„ Z—dS (}  Ú	structurea!  A class to describe and handle information related to a crystal structure.

  It offers various methods to modify the crystallographic information contained.

  Important members are:

  - .special_position_settings (base class)
  - .scatterers
  - .site_symmetry
  - .crystal_symmetry

  NFc             C   s   ||g  d ¡dkst‚|d k	s*|d ks*t‚|d kr>tj|d}tj | |¡ |  ¡  || _|| _|d k	rz| j||| jd d | _	d | _
|| _d S )Né   )Úcrystal_symmetry)Ú
scatterersÚsite_symmetry_tableÚ6non_unit_occupancy_implies_min_distance_sym_equiv_zero)r   ÚAssertionErrorr   Úspecial_position_settingsÚ_copy_constructorÚerase_scatterersÚ7_non_unit_occupancy_implies_min_distance_sym_equiv_zeroÚ_scattering_type_registryÚadd_scatterersr   Úinelastic_form_factors_sourceÚ
wavelength)r   r-   r)   r*   r+   Úscattering_type_registryr(   r4   r    r    r!   r"   8   s$    
zstructure.__init__c             C   sB   t j | t¡ |j| _|j| _|j| _|j| _|j| _|j| _d S )N)	r   r-   r.   Ú_scatterersÚ_site_symmetry_tabler0   r1   Ú(_scattering_type_registry_is_out_of_dater3   )r   Úotherr    r    r!   r.   U   s    zstructure._copy_constructorc             C   s   t j|  ¡ |  ¡ dS )zzGet crystal symmetry of the structure

    :returns: a new crystal symmetry object
    :rtype: cctbx.crystal.symmetry
    )Ú	unit_cellÚspace_group_info)r   Úsymmetryr:   r;   )r   r    r    r!   r(   a   s    zstructure.crystal_symmetryc             C   s
   || _ d S )N)r0   )r   Úvaluer    r    r!   Ú:set_non_unit_occupancy_implies_min_distance_sym_equiv_zerok   s    zDstructure.set_non_unit_occupancy_implies_min_distance_sym_equiv_zeroc             C   s$   t  ¡ | _t ¡ | _d| _d| _dS )z=Remove all scatterers from structure

    :returns: none
    TN)r   Úxray_scattererr6   r	   r*   r7   r8   r3   )r   r    r    r!   r/   n   s    

zstructure.erase_scatterersc             C   s2   t | | j| j| jd}| j ¡ |_| j ¡ |_|S )zŽCreate a deep copy of the structure with all scatterers

    :returns: a new cctbx.xray.structure object
    :rtype: cctbx.xray.structure
    )r5   r+   r4   )r&   r1   r0   r4   r6   Ú	deep_copyr7   )r   Úcpr    r    r!   Údeep_copy_scatterersx   s    
zstructure.deep_copy_scatterersc             C   sp   |t kr| }tjj|||d}|t kr,| j}|t kr:| j}ttj|| j| j	| j
d| j|| j|d}| j|_|S )N)r:   r;   )r(   Úmin_distance_sym_equivÚu_star_toleranceÚassert_min_distance_sym_equiv)r-   r)   r+   r5   r4   )r   r   r<   Úcustomized_copyr0   r4   r&   r-   Ú_min_distance_sym_equivÚ_u_star_toleranceÚ_assert_min_distance_sym_equivr6   r1   r3   )r   r(   r:   r;   r+   r4   Ústrr    r    r!   rF   ‡   s,    zstructure.customized_copyc             C   s   | j S )zŠGet all scatterers of the structure

    :returns: a reference to an array of cctbx.xray.scatterer
    :rtype: cctbx.xray.scatterer[]
    )r6   )r   r    r    r!   r)   ¦   s    zstructure.scatterersc             C   s   | j S )N)r0   )r   r    r    r!   r+   ®   s    z@structure.non_unit_occupancy_implies_min_distance_sym_equiv_zeroc             C   sœ   ||g  d¡dkst‚| j}|dkr6t | ¡ d¡}n| ¡ | ¡ ksJt‚|dk	rr| t | ¡ |¡||  ¡ ¡ n&| ¡ | ¡ ks†t‚| |||  ¡ ¡ | S )aï  Set isotropic mean thermic displacements of scatterers

    :param value: a single double value to set all u_iso of selected     scatterers to
    :type value: double
    :param values: an array of double values to set all u_iso of selected     scatterers to
    :type values: double[]
    :param selection: an array of bools to select scatterers to be updated     with new u_iso values
    :type selection: boolean[]

    :returns: the modified base object
    :rtype: cctbx.xray.structure
    Nr'   T)	r   r,   r6   r   ÚboolÚsizeÚ	set_u_isoÚdoubler:   )r   r=   ÚvaluesÚ	selectionÚsr    r    r!   rM   ±   s      zstructure.set_u_isoc             C   sr   ||g  d¡dkst‚| j}|dk	r:| jt |¡|d n4| ¡ | ¡ ksNt‚|}|t d¡ }| j||d | S )a  Set isotropic Debye-Waller/temperature/B factors with automatic conversion
    to u_iso

    :param value: a single double value to set all b_iso of selected     scatterers to
    :type value: double
    :param values: an array of double values to set all b_iso of selected     scatterers to
    :type values: double[]
    :param selection: an array of bools to select scatterers to be updated with     new b_iso values
    :type selection: boolean[]

    :returns: the modified base object
    :rtype: cctbx.xray.structure
    Nr'   )r=   rP   )rO   rP   )r   r,   r6   rM   r
   Úb_as_urL   )r   r=   rO   rP   rQ   Úb_isoZu_iso_valuesr    r    r!   Ú	set_b_isoÌ   s    zstructure.set_b_isoc             C   sÚ   | j  ¡ }t|d ƒdk r&t |d¡S |dk s6|dkr>tdƒ‚d}d }t|d dƒ}t|d d	ƒ}xrtd
ƒD ]f}x`||krÐt 	|¡| }|dk}	t
||	 d¡ ƒ| }
t||
 ƒ|k rÆt||
 ƒ}|	}|d7 }qrW qlW |S )Ng        gü©ñÒMbP?Tg{®Gáz„?g®Gáz®ï?z'fraction must be between 0.01 and 0.99.g     8@gš™™™™™©?g      ð?é   g-Cëâ6?)r6   rL   Úabsr   rK   ÚRuntimeErrorÚmaxÚminr   Úrandom_doubleÚfloatr   )r   ÚfractionZscatterers_sizeÚtolrP   ÚlÚrÚiÚarrÚselÚdeletedr    r    r!   Úrandom_remove_sites_selectionè   s&    

z'structure.random_remove_sites_selectionc             C   sX   |d k	r|   ¡  ||¡}t| | j| j| jd}| j ¡ }| |¡ ||_| j	 ¡ |_	|S )N)r+   r5   r4   )
Ú
sites_fracÚset_selectedr&   r0   r1   r4   r6   r@   Ú	set_sitesr7   )r   Ú	new_sitesrP   rA   Únew_scatterersr    r    r!   Úreplace_sites_fracý   s    


zstructure.replace_sites_fracc             C   s   | j |  ¡ j|d|dS )N)Ú
sites_cart)rh   rP   )rj   r:   Úfractionalize)r   rh   rP   r    r    r!   Úreplace_sites_cart  s    zstructure.replace_sites_cartc             C   s   | j  ¡  d S )N)r6   Úadjust_u_iso)r   r    r    r!   rn     s    zstructure.adjust_u_isoc             C   sˆ   |dk	r.d|j   d¡dkr.t | j ¡ |¡}| j ¡ }||k}| ||¡}||k}| ||¡}|dkrv| j |¡ n| j ||¡ dS )aq  Adjust site occupancy factor for selected sites to be between occ_min and
    occ_max.

    :param occ_max: maximal site occupancy factor
    :type occ_max: float
    :param occ_min: minimal site occupancy factor
    :type occ_min: float
    :param selection: an array of bools to select scatterers to be adjusted
    :type selection: boolean[]

    :returns: none
    Nz%szarray_family_flex_ext.size_tr   )	Ú	__class__r   r   rK   r6   rL   Úextract_occupanciesrf   Úset_occupancies)r   Zocc_maxZocc_minrP   Úoccrb   r    r    r!   Úadjust_occupancy  s    
zstructure.adjust_occupancyc             C   s   t  | j ¡ d¡S )z–Get a selector array for all scatterers of the structure.

    :returns: an array to select all scatterers of the structure
    :rtype: boolean[]
    T)r   rK   r6   rL   )r   r    r    r!   Úall_selection-  s    zstructure.all_selectionr   c          
   C   sj   |   ¡ }t| | j| j| jd}| j ¡ }| |  ¡ j	|t
 | ¡ |||g¡ d¡ ||_| j ¡ |_|S )ag  Translates all scatterers of this structure by x,y,z.

    :param x: x component of the translation vector
    :type x: float
    :param y: y component of the translation vector
    :type y: float
    :param z: z component of the translation vector
    :type z: float

    :returns: a new translated copy of the structure
    :rtype: cctbx.xray.structure
    )r+   r5   r4   )rk   )rk   r&   r0   r1   r4   r6   r@   rg   r:   rl   r   Úvec3_doublerL   r7   )r   ÚxÚyÚzrk   rA   ri   r    r    r!   Ú	translate5  s    

 zstructure.translatec             C   s`   |dkrt  | j ¡ d¡}|  ¡  |¡}| ¡  |¡}| ¡ | ¡ krNtdƒ‚t  ||  ¡ ¡S )a£  Calculates pairwise distances between the atoms of this structure and
    another structure with the same number of scatterers.

    :param other: the other structure
    :type other: cctbx.xray.structure
    :param selection: an array of bools to select scatterers to be taken into     calculation
    :type selection: boolean[]

    :returns: an array of distances for the selected scatterers
    :rtype: float[]
    NTzModels must be of equal size.)	r   rK   r6   rL   rk   ÚselectrW   ÚsqrtÚdot)r   r9   rP   Ús1Ús2r    r    r!   Ú	distancesP  s     zstructure.distancesc             C   s   t  | j||d¡S )aÒ  Calculates the maximum pairwise distance between the atoms of this
    structure and another structure with the same number of scatterers.

    :param other: the other structure
    :type other: cctbx.xray.structure
    :param selection: an array of bools to select scatterers to be taken into     calculation
    :type selection: boolean[]

    :returns: the maximum distance of two corresponding scatterers out of the     selected scatterers
    :rtype: float
    )r9   rP   )r   rX   r   )r   r9   rP   r    r    r!   Úmax_distanced  s    zstructure.max_distancec             C   s   t  | j||d¡S )aÒ  Calculates the minimum pairwise distance between the atoms of this
    structure and another structure with the same number of scatterers.

    :param other: the other structure
    :type other: cctbx.xray.structure
    :param selection: an array of bools to select scatterers to be taken into     calculation
    :type selection: boolean[]

    :returns: the minimum distance of two corresponding scatterers out of the     selected scatterers
    :rtype: float
    )r9   rP   )r   rY   r   )r   r9   rP   r    r    r!   Úmin_distancet  s    zstructure.min_distancec             C   s   t  | j||d¡S )a¸  Calculates the arithmetic mean pairwise distance between the atoms
    of this structure and another structure with the same number of scatterers.

    :param other: the other structure
    :type other: cctbx.xray.structure
    :param selection: an array of bools to select scatterers to be taken into     calculation
    :type selection: boolean[]

    :returns: the mean pairwise distance of the selected scatterers
    :rtype: float
    )r9   rP   )r   Úmeanr   )r   r9   rP   r    r    r!   Úmean_distance„  s    zstructure.mean_distancec             C   s®   |dk	r |  ¡ | j  ¡ ks2t‚nt | j  ¡ d¡}xvt| j|ƒD ]f\}}|r@|j ¡ r@|j ¡ rl|j	| |_	|j 
¡ r@g }x$tdƒD ]}| |j| | ¡ q„W ||_q@W dS )aÀ  Scale the atomic displacement parameters of the selected scatterers
    of the structure with the specified factor.
    If no selection is given, all scatterers will be handled as if selected.

    :param factor: scale factor to apply to the adps of the selected scatterers
    :type factor: float
    :param selection: an array of bools to select the scatterers to have their     adps scaled
    :type selection: boolean[]

    :returns: none
    NTé   )rL   r6   r,   r   rK   r   ÚflagsÚuseÚ	use_u_isoÚu_isoÚuse_u_anisor   ÚappendÚu_star)r   ÚfactorrP   Úscrb   Úresultr`   r    r    r!   Ú	scale_adp“  s    

 zstructure.scale_adpç      $@çš™™™™™¹?ç      ð?c          
   C   sà  ||g  d ¡dkst‚||g  d ¡dkr4|dks4t‚||g  d ¡dkr’|  ¡  |  ¡ ¡}| ¡ dkr’t t 	|¡¡}	t
|	| ƒ}t
td|	| ƒƒ}|d k	rº|d k	rº||ksºt||||	gƒ‚|d k	rÚ| ¡ | j ¡ ksìt‚nt | j ¡ d¡}|  ¡ j}
xätt ƒ | j|ƒD ]Ð\}}}|r|j ¡ r|j ¡ rb||krbtdt ||d¡t ¡  ƒ}t |¡|_|j ¡ r|sg }x<tdƒD ]0}| |j| |j| t | |f¡  ¡ q‚W |
|drÐ|  ¡  |¡}||_qW d S )	N)r   é   r   g        r“   Tr'   r„   )Úi_seq)r   r,   Úextract_u_iso_or_u_equivrz   r‡   rL   r
   Úu_as_br   r‚   ÚintrX   r6   rK   r*   Úis_special_positionr   r…   r†   ÚrandomÚ	randrangerR   rˆ   r‰   r   rŠ   r‹   ÚchoiceÚspace_groupÚaverage_u_star)r   Úb_maxÚb_minZspreadZaniso_spreadZkeep_anisotropicZrandom_u_cart_scalerP   Úu_isosÚb_meanr˜   r”   r   rb   r_   rŽ   r`   r    r    r!   Ú	shake_adp­  s8     
zstructure.shake_adpc             C   s~   d}|   ¡  d¡dkrz|  ¡ }t t |¡¡}t t |¡¡}t t |¡¡}t	|| ƒ|krzt	|| ƒ|krz|  
¡  d}|S )NFTr   )r‰   r   r•   r
   r–   r   rX   rY   r‚   rV   r¢   )r   Zb_iso_toleranceZ	performedr    rž   rŸ   r¡   r    r    r!   Úshake_adp_if_all_equalÌ  s    z structure.shake_adp_if_all_equalc             C   sh   | j j|  ¡ d}t ¡ }xBt| j ƒD ]4\}}|j ¡ sB|j ¡ r&| 	t
t || ¡ƒ¡ q&W t 
|¡S )N)r:   )r6   Úextract_u_cart_plus_u_isor:   r   rN   Ú	enumerater…   r‡   r‰   rŠ   rY   r
   Úeigenvalues)r   Zu_cartsrŽ   r”   r   r    r    r!   Úmin_u_cart_eigenvalueÙ  s    zstructure.min_u_cart_eigenvaluec             C   sP   | j }t | ¡ ¡d }|d kr,| |¡ n | ¡ | ¡ ks@t‚| ||¡ d S )Ng       @)r6   r   rZ   rL   rq   r,   )r   rP   rQ   Úq_newr    r    r!   Úshake_occupanciesâ  s    zstructure.shake_occupanciesc             C   sr   | j }t dd„ t| ¡ ƒD ƒ¡}|t dd„ |D ƒ¡ }|d krN| |¡ n | ¡ | ¡ ksbt‚| ||¡ d S )Nc             S   s   g | ]}t  d d¡‘qS )r   r'   )r™   Úgauss)Ú.0Ú_r    r    r!   ú
<listcomp>í  s    z'structure.shake_fps.<locals>.<listcomp>c             S   s   g | ]
}|j ‘qS r    )Úfp)r«   r   r    r    r!   r­   î  s    )r6   r   rN   r   rL   Úset_fpsr,   )r   rP   rQ   Úq_deltasr¨   r    r    r!   Ú	shake_fpsë  s    zstructure.shake_fpsc             C   sr   | j }t dd„ t| ¡ ƒD ƒ¡}|t dd„ |D ƒ¡ }|d krN| |¡ n | ¡ | ¡ ksbt‚| ||¡ d S )Nc             S   s   g | ]}t  d d¡‘qS )r   r'   )r™   rª   )r«   r¬   r    r    r!   r­   ÷  s    z(structure.shake_fdps.<locals>.<listcomp>c             S   s   g | ]
}|j ‘qS r    )Úfdp)r«   r   r    r    r!   r­   ø  s    )r6   r   rN   r   rL   Úset_fdpsr,   )r   rP   rQ   r°   r¨   r    r    r!   Ú
shake_fdpsõ  s    zstructure.shake_fdpsc             C   s    |d k	r&t |tjƒr&t | j ¡ |¡}| j}t|dƒrX|}|d k	rh| ¡ | ¡ ksht‚nt | ¡ |¡}|d kr|| 	|¡ n | ¡ | ¡ kst‚| 	||¡ | S )NrL   )
Ú
isinstancer   Úsize_trK   r6   rL   Úhasattrr,   rN   rq   )r   r=   rP   rQ   rO   r    r    r!   rq   ÿ  s    
zstructure.set_occupanciesc             C   s    |d k	r&t |tjƒr&t | j ¡ |¡}| j}t|dƒrX|}|d k	rh| ¡ | ¡ ksht‚nt | ¡ |¡}|d kr|| 	|¡ n | ¡ | ¡ kst‚| 	||¡ | S )NrL   )
rµ   r   r¶   rK   r6   rL   r·   r,   rN   r¯   )r   r=   rP   rQ   rO   r    r    r!   r¯     s    
zstructure.set_fpsc             C   s    |d k	r&t |tjƒr&t | j ¡ |¡}| j}t|dƒrX|}|d k	rh| ¡ | ¡ ksht‚nt | ¡ |¡}|d kr|| 	|¡ n | ¡ | ¡ kst‚| 	||¡ | S )NrL   )
rµ   r   r¶   rK   r6   rL   r·   r,   rN   r³   )r   r=   rP   rQ   rO   r    r    r!   r³   !  s    
zstructure.set_fdpsc             C   sÐ   |d ks|  ¡ | j  ¡ kst‚| j}| ¡   ¡ | j  ¡ ks>t‚ddd| ¡   ¡  dœ}|d krv|d  | j  ¡ 7  < n|d  | d¡7  < x>| ¡ D ]2}|d ksª|| r–|| |¡ ¡  	¡   d7  < q–W |S )Nr   )r   r'   r“   é   r¸   Tr'   )
rL   r6   r,   r7   ÚindicesÚspecial_position_indicesr   ÚgetÚsite_constraintsÚn_independent_params)r   rP   r*   rŽ   r`   r    r    r!   Ú$coordinate_degrees_of_freedom_counts2  s     z.structure.coordinate_degrees_of_freedom_countsc             C   sl   d\}}}d}x@|   ¡  ¡ D ]0}|t| ¡ ƒ7 }|t| ¡ ƒ7 }|| ¡ 7 }qW || dkrh|dkrhd}|S )N)r   r   r   Fr   T)r5   Úunique_gaussians_as_listÚlenÚ
array_of_aÚ
array_of_bÚc)r   ÚacÚbcÚccrŽ   Úuglr    r    r!   Úguess_scattering_type_neutronF  s    
 z'structure.guess_scattering_type_neutronc             C   sd   d}d}xR| j  ¡ D ]D}|d kr"qt| ¡ ƒdksBt| ¡ ƒdkrHd}q| ¡ dkrd}qW |ob|S )NFr   T)r1   r¿   rÀ   rÁ   rÂ   rÃ   )r   Zhas_xrayZhas_neutronrÇ   r    r    r!   Ú6guess_scattering_type_is_a_mixture_of_xray_and_neutronP  s     z@structure.guess_scattering_type_is_a_mixture_of_xray_and_neutronc             C   sš   d}| j d kr|S x‚| j  ¡  ¡ D ]p}|d }|d }d}d}d}|d k	rb| ¡ }| ¡ }| ¡ }|d| d t|ƒ d t|ƒ d t|ƒ 7 }q"W |S )	NÚ r   r'   ÚNonez
  Element: z  a: z  b: z  c: )r1   Úas_type_gaussian_dictÚitemsrÁ   rÂ   rÃ   rJ   )r   rŽ   ÚtgÚstypeÚgaussianÚaaÚabrÃ   r    r    r!   Úscattering_dictionary_as_string\  s    
4z)structure.scattering_dictionary_as_stringc          	   C   s†   g }|   ¡ }|j}t |¡| j ¡ kr.tdƒ‚| | j¡}| | j¡}x:| 	¡  
¡ D ]*\}}| t||| || || d¡ qTW |S )Nz%scattering_type_registry out of date.)Úscattering_typer   Zoccupancy_sumÚunit_cell_occupancy_sum)r5   Úunique_countsr   Úsumr6   rL   rW   Úoccupancy_sumsÚunit_cell_occupancy_sumsÚtype_index_pairs_as_dictrÍ   rŠ   r   )r   rŽ   ÚregrÖ   rØ   rÙ   rÔ   Úunique_indexr    r    r!   Ú*scattering_types_counts_and_occupancy_sumsm  s    z4structure.scattering_types_counts_and_occupancy_sumsc                s>   ddl m‰  t‡ fdd„|  ¡ D ƒƒ}|  ¡  ¡ }d| | S )aÜ  Get the value of the diffraction-determined density for the crystal,
    suitable for the CIF item _exptl_crystal_density_diffrn

    Density values are calculated from the crystal cell and contents. The
    units are megagrams per cubic metre (=grams per cubic centimetre).

    Equivalent to:
      1.66042 * _chemical_formula_weight * _cell_formula_units_Z / _cell_volume

    :returns: chemical density in megagrams per cubic metre (=grams per cm^3)
    :rtype: float
    r   )Útiny_psec                s"   g | ]}ˆ   |j¡ ¡ |j ‘qS r    )r   rÔ   ÚweightrÕ   )r«   Úelt)rÞ   r    r!   r­   Œ  s   z-structure.crystal_density.<locals>.<listcomp>g7ýÙ‘ú?)Úcctbx.eltbxrÞ   r×   rÝ   r:   Úvolume)r   Ú	numeratorÚdenominatorr    )rÞ   r!   Úcrystal_density}  s    
zstructure.crystal_densityc             C   sâ   d}|   ¡ }|j}t |¡| j ¡ kr.tdƒ‚| | j¡}| d¡}x,| 	¡  
¡ D ]\}}||| ||  7 }qRW |sz|S d}	d}
xL|  ¡ D ]@}|jr®|	|j|j | ¡  7 }	|jrŒ|
|j|j | ¡  7 }
qŒW tt||	 |
ƒƒS )a©  Get the effective number of electrons in the crystal unit cell
    contributing to F(000), suitable for the CIF item _exptl_crystal_F_000.

    According to the CIF definition, this item **may** contain dispersion
    contributions.

    :param include_inelastic_part: If 'True' contributions due to dispersion     are included in F(000).
    :type include_inelastic_part: boolean

    :returns: F(000)
    :rtype: float
    r   z%scattering_type_registry out of date.)r5   rÖ   r   r×   r6   rL   rW   rÙ   Ú unique_form_factors_at_d_star_sqrÚ   rÍ   r)   r®   Ú	occupancyÚmultiplicityr²   rV   Úcomplex)r   Zinclude_inelastic_partZelastic_partrÛ   rÖ   rÙ   Zunique_form_factors_at_originrÔ   rÜ   Zinelastic_part_realZinelastic_part_imagr   r    r    r!   Úf_000‘  s(    
zstructure.f_000c          	   C   sª  ||g  d¡dkst‚|dk	r0|dks*t‚|}n|dks<t‚|}|dkrLdS | j ¡ dks^t‚| j}| ¡  ¡ | j ¡ ks~t‚|dk	r¼| ¡ | j ¡ ksœt‚|  d¡}|dkr¶tdƒ‚d}	n| j ¡ }d}	t ¡ }
xB| 	¡ D ]6}| 
|¡ ¡  ¡ dkrÜ|dks|| rÜ|
 |¡ qÜW ||
 ¡ 8 }|dkrB|r6dS td	|	 ƒ‚|| j ¡ krVd}| j}|  ¡ j}|  ¡ j}|dkr€tj}xütd
dD ]î}t || j ¡ d ddd ¡}|dk	rÈ| | d¡ | |
d¡ x\| 	¡ D ]P}t || j¡}| 
|¡ ¡ |t ||| ƒ¡  }|t |¡| ƒ||< qÞW |dk	rTt | ¡ ¡| d }nt t | ¡ ¡¡| }|dkrŒP qŒW ||| 9 }|  |  ¡ |  ¡  |¡ ¡ dS )a%  Shake the coordinates of the selected scatterers in this structure.

    :param rms_difference: radial mean square displacement (>=0) to apply to     selected scatterers
    :type rms_difference: float
    :param mean_distance: a mean distance shift (>=0) to apply to selected     scatterers
    :type mean_distance: float
    :param selection: an array of bools to select scatterers to be shaken
    :type selection: boolean[]
    :param allow_all_fixed: if set to 'True' shaking a structure with all     scatterers on fixed special positions will not cause an error
    :type allow_all_fixed: boolean
    :param random_double: "random" numbers to use for displacements
    :type random_double: float[]

    :returns: 'True' if at least one scatterer was moved, 'False' otherwise
    :rtype: boolean
    Nr'   r   TzNo scatterers selected.z	 selectedrÊ   Fz0All%s scatterers are fixed on special positions.é
   )Úassert_less_thanr¸   r“   )rL   rŒ   )r   r   r   g      à?gíµ ÷Æ°>)r   r,   r6   rL   r7   r¹   rW   r   r¶   rº   r»   r¼   r½   rŠ   r:   rl   ÚorthogonalizerZ   r   ru   rf   r   ÚcolÚsiteÚ
special_opr×   r|   r{   Úset_sites_fracre   )r   Úrms_differencerƒ   rP   Zallow_all_fixedrZ   Ztarget_differencer*   Z
n_variableÚallÚselection_fixedr`   r)   ÚfracÚorthZshifts_cartZsite_frac_origÚ	site_fracÚ
differencer    r    r!   Úshake_sites_in_place´  st     









 zstructure.shake_sites_in_placec                s~  ˆdkrdS ˆj }| ¡  ¡ ˆj ¡ ks,t‚ˆ ¡ j‰ˆ ¡ j‰ˆdkrTtj	dd‰t
j‰xtˆjƒD ]\}‰ˆˆjƒ‰	| |¡‰
ˆ
 ¡ ‰ˆ ¡ }|dkr qh|dkrÈ‡‡‡‡‡‡‡	fdd„}|ƒ  qh|dkrRg }xhdD ]`}xZdD ]R}	tˆ ˆ	¡ƒ}
|
d  |7  < |
d	  |	7  < | ˆˆˆˆ |
¡ƒˆ	 ƒƒ¡ qæW qÜW t|ƒd
ksRt‚d‰ d}xjtdƒD ]^}|| }xNt|d	 d
ƒD ]<}|| }| |¡}| ¡ }ˆ dks²||kr€|‰ |}q€W qdW ˆ dk	sÔt‚|dksât‚d}d}x2|D ]*‰ˆ ¡ }|dks||krðˆ}|}qðW |dk	s,t‚‡ ‡‡‡‡‡‡‡	‡
‡f
dd„}|ƒ  qh‡‡‡‡‡‡‡‡‡	‡
f
dd„}|ƒ  qhW dS )a1  Shifts the coordinates of all scatterers in this structure.

    :param shift_length: the distance to shift each scatterer with
    :type shift_length: float
    :param mersenne_twister: a mersenne twister to use as entropy source
    :type mersenne_twister: flex.mersenne_twister

    :returns: none
    r   N)Úseedr¸   c                 sn   ˆ} xd| dkrhxNt dƒD ]B}ˆ ˆˆ ˆ ¡ ƒ|  ƒƒ}ˆ| }ˆj|d}| ¡ r|ˆ_d S qW | d9 } qW d S )Nr   rë   )rï   g      à?)r   Úrandom_double_point_on_sphereÚsite_symmetryÚis_point_group_1rï   )ÚslÚi_trialÚ
shift_fracÚsite_modÚss_mod)rî   rõ   Úmersenne_twisterr   r   Úshift_lengthr÷   r    r!   Úfind_3$  s    
z.structure.shift_sites_in_place.<locals>.find_3r“   )éÿÿÿÿr   r'   r'   é	   é   c                 s’   ˆ} xˆ| dkrŒxrt ddD ]d}ˆ jˆ ¡ d tj d}ˆˆ|ˆ	  ¡ |  ƒƒ}ˆ| }ˆj|d}| ¡ ˆ ¡ kr|ˆ_d S qW | d9 } qW d S )Nr   rë   )rì   r“   )Úangle)rï   g      à?)	r   Ú$axis_and_angle_as_r3_rotation_matrixrZ   ÚmathÚpiÚ	normalizerü   rð   rï   )rþ   rÿ   r_   r   r  r  )
Úaxisrî   rõ   r  r   r   r  r÷   ÚssÚvr    r!   Úfind_2P  s    
z.structure.shift_sites_in_place.<locals>.find_2c                 sÔ   ˆ} xÊ| dkrÎˆ  ¡ dk r$ddg}nddg}x–|D ]Ž}tˆ ˆ¡ƒ}|d  |7  < ˆ ˆˆ ˆ |¡ƒˆ ƒƒ}| ¡ dks~t‚ˆ ˆ| ¡ ˆ ƒƒ}ˆ| }ˆj|d}| ¡ ˆ	 ¡ kr2|ˆ_	d S q2W | d9 } qW d S )Nr   g      à?r'   r  )rï   )
rZ   ÚlistÚindependent_paramsÚ
all_paramsÚlengthr,   r  rü   rð   rï   )rþ   ÚusÚuÚindepr  r   r  r  )
rî   Úconstrrõ   r  rö   r   r   r  r÷   r  r    r!   Úfind_1_  s"    


z.structure.shift_sites_in_place.<locals>.find_1)r7   r¹   rL   r6   r,   r:   rl   rí   r   r  r   rî   r¥   rï   r»   r¼   r½   r  r  rŠ   r  rÀ   r   Úcrossr  )r   r  r  ZsstÚi_scÚnpr  Zplane_vectorsÚs0r}   r  Úaxis_lengthr`   ÚviÚjZvjr  r  Zv_maxZl_maxr^   r  r  r    )r  rî   r  rõ   r  rö   r   r   r  r÷   r  r  r!   Úshift_sites_in_place
  sl    
 






 


zstructure.shift_sites_in_placec             C   s<   | j  ¡ t d¡ }t |¡}t |¡}t |¡}|||fS )zÔGet the minimal, maximal and mean isotropic Debye-Waller/temperature/B     factors of all scatterers in this structure.

    :returns: minimal b_iso, maximal b_iso, mean b_iso
    :rtype: float, float, float
    r'   )r6   Úextract_u_isor
   rR   r   rY   rX   r‚   )r   Zb_isosrŸ   rž   r¡   r    r    r!   Úb_iso_min_max_meant  s
    


zstructure.b_iso_min_max_meanc             C   s
   d| _ d S )NT)r8   )r   r    r    r!   Ú discard_scattering_type_registry  s    z*structure.discard_scattering_type_registryc             C   s   t  | j¡S )N)r   Ún_undefined_multiplicitiesr6   )r   r    r    r!   r&  „  s    z$structure.n_undefined_multiplicitiesc             C   s
   | j  ¡ S )N)r6   Úextract_sites)r   r    r    r!   re   ‡  s    zstructure.sites_fracc             C   s
   | j  ¡ S )N)r6   Úextract_use_u_iso)r   r    r    r!   r‡   Š  s    zstructure.use_u_isoc             C   s
   | j  ¡ S )N)r6   Úextract_use_u_aniso)r   r    r    r!   r‰     s    zstructure.use_u_anisoc             C   s&   |  ¡ | j  ¡ kst‚| j |¡ dS )zùSet the the fractional coordinates of all sites of the structure to     'sites_frac'.

    :param sites_frac: a list of the fractional coordinates for all scatterers
    :type sites_frac: scitbx.array_family.flex.vec3_double

    :returns: none
    N)rL   r6   r,   rg   )r   re   r    r    r!   rñ     s    	zstructure.set_sites_fracc             C   s   |   ¡ j|  ¡ dS )zÃGet the the cartesian coordinates of all sites of the structure.

    :returns: a list of the sites of the structure in cartesian coordinates
    :rtype: scitbx.array_family.flex.vec3_double
    )re   )r:   rí   re   )r   r    r    r!   rk   œ  s    zstructure.sites_cartc             C   s   |   |  ¡ j|d¡ dS )z÷Set the the cartesian coordinates of all sites of the structure to     'sites_cart'.

    :param sites_cart: a list of the cartesian coordinates for all scatterers
    :type sites_cart: scitbx.array_family.flex.vec3_double

    :returns: none
    )rk   N)rñ   r:   rl   )r   rk   r    r    r!   Úset_sites_cart¤  s    	zstructure.set_sites_cartc             C   s2   t  ¡ }x$| j ¡ D ]}| | ¡  ¡ ¡ qW |S )N)r   Ú
std_stringr6   Úextract_scattering_typesrŠ   ÚstripÚupper)r   rŽ   Úsctr    r    r!   Úscattering_types¯  s    zstructure.scattering_typesc             C   s   | j j|  ¡ dS )N)r:   )r6   r¤   r:   )r   r    r    r!   r¤   µ  s    z#structure.extract_u_cart_plus_u_isoc             C   s   | j j|  ¡ dS )N)r:   )r6   r•   r:   )r   r    r    r!   r•   ¹  s    z"structure.extract_u_iso_or_u_equivc             C   s   |   ¡ t d¡ S )Ng      ð?)r•   r
   r–   )r   r    r    r!   Úb_iso_or_b_equiv½  s    zstructure.b_iso_or_b_equivc             C   s   | j  |¡S )N)r6   Ú
scale_adps)r   Úscale_factorr    r    r!   r2  À  s    zstructure.scale_adpsc             C   s   | j dd ¡ S )NÚneutron)r   )r5   rÌ   )r   r    r    r!   Ú'switch_to_neutron_scattering_dictionaryÃ  s    z1structure.switch_to_neutron_scattering_dictionaryc             C   sF   | j  ¡ }t ¡ }x.|D ]&}| ¡ dkr4| d¡ q| d¡ qW |S )zµGet a selector array for all hydrogen and deuterium scatterers of the structure.

    :returns: an array to select all H and D scatterers of the structure
    :rtype: boolean[]
    )ÚHÚDTF)r6   r,  r   rK   r-  rŠ   )r   r0  rŽ   r/  r    r    r!   Úhd_selectionÉ  s    

 zstructure.hd_selectionc       
      C   sè   |r|rt dƒ‚| j ¡ }|  ¡ }t ¡ }x¸t|ƒD ]¬\}}|rb|| jdd… dkrb| d¡ q4|rˆ|| jdd… dkrˆ| d¡ q4|r¾x0dD ]}	|| jdd… |	kr’P q’W | d¡ q4| 	¡ dkrÖ| d¡ q4| d	¡ q4W |S )
a_  Get a selector array for heavy (= non H or D) scatterers of the structure.

    :param ignore_atoms_with_alternative_conformations: select normal atoms/conformations only
    :type ignore_atoms_with_alternative_conformations: boolean
    :param include_only_atoms_with_alternative_conformations: select only scatterers with alternative conformations
    :type include_only_atoms_with_alternative_conformations: boolean
    :param only_protein: select only protein scatterers
    :type only_protein: boolean

    :returns: an array to select the desired scatterers of the structure
    :rtype: boolean[]
    z/Mutually exclusive alternative location optionsr  rë   ú F)ÚALAÚCYSÚASPÚGLUÚPHEÚGLYÚHISÚILEÚLYSÚLEUÚMETÚASNÚPROÚGLNÚARGÚSERÚTHRÚVALÚTRPÚTYRé   )r6  r7  T)
r   r6   r,  r)   r   rK   r¥   ÚlabelrŠ   r-  )
r   Ú+ignore_atoms_with_alternative_conformationsÚ1include_only_atoms_with_alternative_conformationsZonly_proteinr0  r)   rŽ   r`   r/  Úresnamer    r    r!   Úheavy_selection×  s2    




 zstructure.heavy_selectionÚCÚOÚCAÚNc             C   sæ   |r|rt dƒ‚| j ¡ }t ¡ }x¾|  ¡ D ]²}|j d¡dkrL| d¡ q,|rn|jdd… dkrn| d¡ q,|r|jdd… dkr| d¡ q,xL|D ]:}|jdd…  d	| ¡dkr–|j	|d
 kr–| d¡ P q–W | d¡ q,W |S )ac  Get a selector array for scatterers of the structure by "atom" names.

    :param atom_names: list of labels of scatterers to select
    :type atom_names: list(string)
    :param ignore_atoms_with_alternative_conformations: select normal atoms/conformations only
    :type ignore_atoms_with_alternative_conformations: boolean
    :param include_only_atoms_with_alternative_conformations: select only scatterers with alternative conformations
    :type include_only_atoms_with_alternative_conformations: boolean

    :returns: an array to select the desired scatterers of the structure
    :rtype: boolean[]
    z/Mutually exclusive alternative location optionsÚHOHr  Fr  rë   r9  rU   z%s r   T)
r   r6   r,  r   rK   r)   rO  ÚfindrŠ   rÔ   )r   Ú
atom_namesrP  rQ  r0  rŽ   r   Únamer    r    r!   Úatom_names_selection  s0    





zstructure.atom_names_selectionc             C   s   | j |||dS )a™  Get a selector array for scatterers of the backbone of the structure.
    (This is just an alias for atom_names_selection.)

    :param atom_names: list of labels of scatterers to select
    :type atom_names: list(string)
    :param ignore_atoms_with_alternative_conformations: select normal atoms/conformations only
    :type ignore_atoms_with_alternative_conformations: boolean
    :param include_only_atoms_with_alternative_conformations: select only scatterers with alternative conformations
    :type include_only_atoms_with_alternative_conformations: boolean

    :returns: an array to select the desired scatterers of the structure
    :rtype: boolean[]
    )rZ  rP  rQ  )r\  )r   rZ  rP  rQ  r    r    r!   Úbackbone_selectionF  s    zstructure.backbone_selectionÚCBc             C   s   | j |||dS )a¾  Get a selector array for scatterers of the main chain of the structure.
    (This is just an alias for atom_names_selection with a different default selection.)

    :param atom_names: list of labels of scatterers to select
    :type atom_names: list(string)
    :param ignore_atoms_with_alternative_conformations: select normal atoms/conformations only
    :type ignore_atoms_with_alternative_conformations: boolean
    :param include_only_atoms_with_alternative_conformations: select only scatterers with alternative conformations
    :type include_only_atoms_with_alternative_conformations: boolean

    :returns: an array to select the desired scatterers of the structure
    :rtype: boolean[]
    )rZ  rP  rQ  )r\  )r   rZ  rP  rQ  r    r    r!   Úmain_chain_selection^  s    zstructure.main_chain_selectionc             C   s   | j |||dS )a½  Get a selector array for peptide dihedral scatterers of the structure.
    (This is just an alias for atom_names_selection with a different default selection.)

    :param atom_names: list of labels of scatterers to select
    :type atom_names: list(string)
    :param ignore_atoms_with_alternative_conformations: select normal atoms/conformations only
    :type ignore_atoms_with_alternative_conformations: boolean
    :param include_only_atoms_with_alternative_conformations: select only scatterers with alternative conformations
    :type include_only_atoms_with_alternative_conformations: boolean

    :returns: an array to select the desired scatterers of the structure
    :rtype: boolean[]
    )rZ  rP  rQ  )r\  )r   rZ  rP  rQ  r    r    r!   Úpeptide_dihedral_selectionv  s    z$structure.peptide_dihedral_selectionc                s   t  ‡ fdd„|  ¡ D ƒ¡S )a1  Get a selector array for scatterers of specified element type(s) of the structure.

    :param elements: tuple of element symbols to select
    :type elements: list(string) or set(string) or tuple(string)

    :returns: an array to select the desired scatterers of the structure
    :rtype: boolean[]
    c                s   g | ]}|  ¡  ¡ ˆ k‘qS r    )Úelement_symbolr-  )r«   r   )Úelementsr    r!   r­   —  s   z/structure.element_selection.<locals>.<listcomp>)r   rK   r)   )r   rb  r    )rb  r!   Úelement_selectionŽ  s    	zstructure.element_selectionc                s   t  ‡ fdd„|  ¡ D ƒ¡S )a'  Get a selector array for scatterers of specified labels from the structure.

    :param labels: tuple of scatterer labels to select
    :type labels: list(string) or set(string) or tuple(string)

    :returns: an array to select the desired scatterers of the structure
    :rtype: boolean[]
    c                s   g | ]}|j ˆ k‘qS r    )rO  )r«   r   )Úlabelsr    r!   r­   £  s    z-structure.label_selection.<locals>.<listcomp>)r   rK   r)   )r   rd  r    )rd  r!   Úlabel_selectionš  s    	zstructure.label_selectionc                s6   t ˆ ƒrddl}| ˆ ¡‰ t ‡ fdd„|  ¡ D ƒ¡S )aC  Get a selector array for scatterers of specified labels (via regular
    expression) from the structure.

    :param label_regex: a regular expression matching scatterer labels to select
    :type label_regex: string or re

    :returns: an array to select the desired scatterers of the structure
    :rtype: boolean[]
    r   Nc                s   g | ]}ˆ   |j¡d k	‘qS )N)ÚsearchrO  )r«   r   )Úlabel_regexr    r!   r­   ²  s   z3structure.label_regex_selection.<locals>.<listcomp>)r   ÚreÚcompiler   rK   r)   )r   rg  rh  r    )rg  r!   Úlabel_regex_selection¥  s
    

zstructure.label_regex_selectionc             C   sJ   t  | j ¡ d¡}y| t  |¡d¡ W n tk
rD   tdƒ‚Y nX |S )ar  Get a selector array for scatterers with specified index from the
    structure. For example you can select scatterers 1,4 and 5 by passing
    (1,4,5) as argument.

    :param selected_scatterers: list of scatterers to select
    :type selected_scatterers: list(int)

    :returns: an array to select the desired scatterers of the structure
    :rtype: flex.bool[]
    FTzVTried to select a scatterer by index with index => of scatterers for this structuture.)r   rK   r6   rL   rf   r¶   rW   Ú
IndexError)r   Zselected_scatterersrŽ   r    r    r!   Úby_index_selectionµ  s    zstructure.by_index_selectionTc          	   C   sx   |d krt  | j ¡ d¡ ¡ }| j|  ¡ |  ¡ ||||  ¡ |  	¡ d}| j
|jd |rt|  ¡ }|  ¡  | j|d d S )NT)rk   re   ÚrotÚtransrP   r:   Úatomic_weights)re   )r)   )r   rK   r6   rL   Ú
iselectionÚapply_rigid_body_shift_objrk   re   r:   ro  rñ   r)   r/   r2   )r   rm  rn  rP   Úrecompute_site_symmetriesZrbs_objr)   r    r    r!   Úapply_rigid_body_shiftÈ  s    z structure.apply_rigid_body_shiftc          	   C   s   t j|||||||dS )N)rk   re   rm  rn  ro  r:   rP   )r   rs  )r   rk   re   rm  rn  rP   r:   ro  r    r    r!   rq  Ú  s    z$structure.apply_rigid_body_shift_objc             C   s4   |d kr| j j|  ¡ d n| j j|  ¡ |d d S )N)r:   )r:   rP   )r6   Úconvert_to_isotropicr:   )r   rP   r    r    r!   rt  ê  s    zstructure.convert_to_isotropicc             C   s4   |d kr| j j|  ¡ d n| j j|  ¡ |d d S )N)r:   )r:   rP   )r6   Úconvert_to_anisotropicr:   )r   rP   r    r    r!   ru  ò  s    z structure.convert_to_anisotropicrÊ   c          	   C   sŠ  |d krt j}| j ¡ }|r*t |d¡}n|  ¡ }dtjd  }|  	¡  
| ¡}|  ¡  
| ¡}||B }	| d¡}
| d¡}|  ¡  
| ¡}| d¡}| d¡}|  ¡ |  
| ¡ 
|	¡}|  ¡  ¡ |  
| ¡ 
|¡}| ¡ dkrè|}d| }d}dt|| ƒ }t|d	|  | |d
 dt|d ƒ }td||
||f |d
 tdt |¡t |¡t |¡f d d |d
 tdt |¡t |¡t |¡f d d |d
 td|d
 td|d
 td|d
 tj|dd}| ¡ }tj|dd}| ¡ }x„tt| ¡ ƒt| ¡ ƒƒD ]f\\}}\}}| ¡ | ¡ |d   }| ¡ | ¡ |d   }td||||||f |d
 |}|}qW td|d
 d S )NTr  r“   Fr   z|-z-|éO   ú-)Úfileú|zK| iso = %-5d   aniso = %-5d   pos. def. = %-5d   non-pos. def. = %-5d     |zL| Total B(isotropic equivalent): min = %-6.2f   max = %-6.2f   mean = %-6.2fz  zL| Isotropic B only:              min = %-6.2f   max = %-6.2f   mean = %-6.2fzO| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |zO|                     Distribution of isotropic B-factors:                    |zO|            Isotropic                |             Total                     |rë   )ÚdataZn_slotsr'   z5|  %9.3f -%9.3f:%8d      |    %9.3f -%9.3f:%8d      |zO|-----------------------------------------------------------------------------|)ÚsysÚstdoutr6   rL   r   rK   r8  r  r  r‰   rz   r‡   r   Úis_positive_definite_ur•   r)   r#  rÀ   ÚprintrY   rX   r‚   Ú	histogramÚdata_minr   r¥   ÚslotsÚ
slot_width)r   ÚtextÚoutZuse_hydrogensrL   r8  Zepisr‰   r‡   Zsel_usedZn_anisotropicZn_isotropicZipdZnpdZnnpdZbeqZbisosZpart1Zpart2ÚnÚhistogram_1Zlow_cutoff_1Úhistogram_2Zlow_cutoff_2Zi_1Zn_1Zi_2Zn_2Zhigh_cutoff_1Zhigh_cutoff_2r    r    r!   Úshow_u_statisticsù  s`     




 ..
zstructure.show_u_statisticsc             C   s   | j S )N)r7   )r   r    r    r!   r*   ,  s    zstructure.site_symmetry_tablec             C   s
   | j  ¡ S )N)r7   rº   )r   r    r    r!   rº   /  s    z"structure.special_position_indicesc             C   sò  |dkst ‚|dkr(|dks(|dks(t ‚|dkrD|dksD|dksDt ‚|dkr`|dks`|dks`t ‚| jsˆ|d k	sˆ|d k	sˆ|d k	sˆ|d k	rÄt||||d| _d	tj d
¡i}i }d }| jd k	r(| j ¡ }| j ¡ }	| j 	¡ }
x,|
 
¡ D ] \}}|	| d k	ræ|	| ||< qæW |d kr(|d kr(| |¡ |d k	rRx|D ]}tj d¡||< q8W |d k	rf| |¡ |d krtd}t ¡ | _| j | j¡ x.| j ¡ D ]}| |d ¡}|d krŠtjj|ddd}|d k	rŠ|d krâ|}n|}|dkrtj |d¡ ¡ }n†|dkr"tj |d¡ ¡ }nh|dkrFddlm} ||dd}nD|dkrrt|dƒ}| ¡ }tj |j¡}ntj ||d¡ ¡ }d}|d k	rš| j ||¡ |d k	rš| j |¡ qšW d| _|sì|  ¡ rìd}||  ¡ 7 }t |ƒ‚| jS )N)NÚ
n_gaussianÚit1992Úwk1995ÚxrayÚelectronr4  rŠ  )r   Ng      Ð?r‹  gUUUUUUµ?r  )r   r   r   r   Úconstr'   r   T)rO  ÚexactÚoptional)Ú.ito_vol_c_2011_table_4_3_2_2_entry_as_gaussian)rO  r  r4  r‰  Fz)Mixed xray and neutron scattering table! )!r,   r8   r   r   Úxray_scatteringrÐ   r1   Ú
last_tabler¿   rÚ   rÍ   Úupdater   r5   Úprocessr6   Úunassigned_typesr»   Úget_standard_labelrŠ  Úfetchr‹  Zcctbx.eltbx.e_scatteringr‘  r   Úbound_coh_scatt_lengthÚrealÚn_gaussian_table_entryÚassignÚset_last_tablerÉ   rÓ   rW   )r   r   r   r   r   Zexplicitly_allow_mixingZnew_dictZold_dictZlast_used_scattering_tableÚugsZtipÚtr`   Zt_undefÚvalÚstd_lblr¬   Úscattering_infoÚbÚerrmsgr    r    r!   r5   2  s       




 





 











z"structure.scattering_type_registryc             C   sF   |dkrt j}n|dkr t j}ntd| ƒ‚|| _||  ¡ ||ƒ d S )NÚsasakiÚhenkez(Unknown inelastic form factors table: %s)r   Ú&set_inelastic_form_factors_from_sasakiÚ%set_inelastic_form_factors_from_henkerW   r3   r)   )r   Zphotonr   Úset_use_fp_fdpZset_inelastic_ffr    r    r!   Úset_inelastic_form_factors‡  s    z$structure.set_inelastic_form_factorsÚcustomc             C   sj   x^|   ¡ D ]R}| |jd¡}|dkr8d|_d|_d|_q
|d |_|d |_|r
|j d¡ q
W || _dS )z¬ Expects a dictionary of tuples like 'C' : (fp, fdp). If an element is
    not in the dictionary, the fp and fdp are reset to 0 and the use_fp_fdp is
    set to false.
    Nr   Fr'   T)	r)   r»   rÔ   r®   r²   Ú
use_fp_fdpr…   r©  r3   )r   r   r©  Úsourcer   Zfp_fdpr    r    r!   Ú!set_custom_inelastic_form_factors‘  s    

z+structure.set_custom_inelastic_form_factorsc             C   s   |   ¡ }| ¡ |  ¡  ¡  S )N)r5   Ú0sum_of_scattering_factors_at_diffraction_angle_0r:   râ   )r   r_   r    r    r!   Úmean_scattering_density¤  s    z!structure.mean_scattering_densityc             C   sZ   t |ƒtkst‚|  ¡ d k	s t‚tj| j ¡ |d}t| | j 	|¡| j
 	|¡| j| jdS )N)Z
array_sizeZpython_slice)r-   r)   r*   r5   r4   )ÚtypeÚslicer,   r)   r   Úslice_indicesr6   rL   r&   rz   r7   r1   r4   )r   Úslice_objectrb   r    r    r!   Ú__getitem__©  s    

zstructure.__getitem__c             C   s@   |   ¡ d k	st‚|r| }t| | j |¡| j |¡| j| jdS )N)r-   r)   r*   r5   r4   )r)   r,   r&   r6   rz   r7   r1   r4   )r   rP   Únegater    r    r!   rz   ¶  s     

zstructure.selectc             C   s6   |   ¡ d k	st‚| j |¡| _| j |¡| _d| _d S )NT)r)   r,   r6   rz   r7   r8   )r   rP   r    r    r!   Úselect_inplaceÀ  s    zstructure.select_inplacec             C   sŠ   |d kr| j  ¡ }| j  ||¡ |d krX| j | j|  ¡ |  ¡ |  ¡ |  ¡ |  ¡ d}n| j | j||  ¡ d | j	j
||d d| _d S )N)r:   rœ   rC   rD   rE   )Úsite_symmetry_opsrD   )Úinsert_at_indexr¸  T)r6   rL   ÚinsertÚapply_symmetryr:   rœ   rC   rD   rE   r7   r•  r8   )r   Ú	scattererr¸  r¹  r    r    r!   Úadd_scattererÆ  s     



zstructure.add_scattererc             C   s|   |d krt  ¡ }n | ¡  ¡ | ¡ ks*t‚|r2t‚| j |¡ tj|  	¡ |  
¡ | j| j||  ¡ |  ¡ |  ¡ |d	 d| _d S )N)	r:   rœ   r)   r*   Zsite_symmetry_table_for_newrC   rD   rE   r+   T)r	   r*   r¹   rL   r,   r6   Úextendr   Úadd_scatterers_extr:   rœ   r7   rC   rD   rE   r8   )r   r)   r*   r+   r    r    r!   r2   Ü  s     
zstructure.add_scatterersc             C   s   |   ¡ }|j|j|jd |S )N)r)   r*   )rB   r2   r6   r7   )r   r9   rŽ   r    r    r!   Úconcatenateó  s
    
zstructure.concatenatec             C   sT  |   ¡  ¡ }|  ¡  ¡ }xätj | ¡ t |¡¡D ]È\}}x¾tj | ¡ t |¡¡D ]¢\}}||krT|d }|d }	d}
x,t| ¡ |	 ¡ ƒD ]\}}t||ƒsŒd}
qŒW x,t| 	¡ |	 	¡ ƒD ]\}}t||ƒsºd}
qºW t| 
¡ |	 
¡ ƒsêd}
|
rTtdƒ‚qTW q2W | j|j|jd | j}|j}| j |j|j|j|jd | j |j|j|j|jd d S )Nr'   FTz*Cannot concatenate: conflicting scatterers)r)   r*   )r   r   r   r   )r5   rÌ   ÚsixÚmovesr   ÚkeysÚ	iteritemsrÁ   r   rÂ   rÃ   rW   r2   r6   r7   r   r   r   r   r   )r   r9   Úd1Úd2Úkey1Zitem1Úkey2Zitem2Úi1Úi2Zproblem_flagÚa1Úa2Úb1Úb2Zstrp1Zstrp2r    r    r!   Úconcatenate_inplaceú  s@    ""
 
  

zstructure.concatenate_inplacec             C   sD   |dkst ‚|  ¡ d k	st ‚tj|  ¡ j||  ¡ d|dj|dS )Nr   )Úbuffer_thicknessrk   )Úasu_mappingsÚdistance_cutoff)Zprimary_selection)r,   r-   r   Úneighbors_fast_pair_generatorrÑ  rk   Úneighbors_of)r   ÚradiusrP   r    r    r!   Úselection_within  s    
zstructure.selection_withinÚexistingc             C   sL   |dkr| j }|d k	r2| ¡  ¡ |  ¡  ¡ ks2t‚|  ¡  | j||d d S )Nr×  )r)   r*   )r7   r¹   rL   r)   r,   r/   r2   )r   r)   r*   r    r    r!   Úreplace_scatterers%  s    zstructure.replace_scatterersc	       
   	   C   sp   |dkr$|   ¡  ¡ dkrd}q@d}n|s@|   ¡  ¡ dkr@tdƒ‚t | ||¡}	tj| ||||||d| |	|dS )aÁ  
    Calculate structure factors for the current scatterers using either direct
    summation or FFT method; by default the appropriate method will be guessed
    automatically.

    :param anomalous_flag: toggles whether the returned structure factors are
      anomalous or not
    :type anomalous_flag: bool
    :param d_min: resolution cutoff (required)
    :type d_min: float
    :param algorithm: specifies 'direct' or 'fft', or if None (default), the
      algorithm will be chosen automatically
    :type algorithm: str or None
    :param cos_sin_table: if True, uses interpolation of values from a
      pre-calculated lookup table for trigonometric function calls in the
      structure factor calculations in preference to calling the system
      libraries
    :type cos_sin_table: bool
    :param quality_factor: determines accuracy of sampled density in fft method
    :type quality_factor: float
    :param u_base: additional smearing B-factor for scatterers which have too
      small Bs so they fall between the grid nodes
    :type u_base: float
    :param b_base: same as u_base (but 8*pi^2 larger)
    :type b_base: float
    :param wing_cutoff: is how far away from atomic center you sample density
      around atom
    :type wing_cutoff: float

    :returns: a custom Python object (exact type depends on method used), from
      which f_calc() may be called
    :rtype: derived from cctbx.xray.structure_factors.manager.managed_calculation_base
    Nr   TFzKxray.structure with anomalous scatterers but miller.array is non-anomalous.)r(   r   Úcos_sin_tableÚquality_factorÚu_baseÚb_baseÚwing_cutoff)Úxray_structureÚ
miller_setÚ	algorithm)r)   Úcount_anomalousrW   r   Ú	build_setr   Úfrom_scatterers)
r   Úanomalous_flagr   rà  rÙ  rÚ  rÛ  rÜ  rÝ  rß  r    r    r!   r   /  s(    (zstructure.structure_factorsc             C   st   d|||   ¡ j|d d|f }g }x<t|  ¡ ƒD ],\}}| |d |j|d d| d ¡ q2W |d |¡ d S )	z¡eval(self.as_py_code()) is similar (but sometimes not identical)
    to self and meant to enable quick formatting of self as Python code
    for unit tests.
    zP%sxray.structure(
%s  crystal_symmetry=%s,
%s  scatterers=flex.xray_scatterer([
z  )Úindentz    z #%d)rå  Úcommentz,
z])))r(   Ú
as_py_coder¥   r)   rŠ   Újoin)r   rå  Úr0Úr1r`   r   r    r    r!   rç  n  s    $zstructure.as_py_codec             C   sX   |d krt j}t|d |  ¡  ¡ |d t|d |  ¡  ¡ |d tjj| ||d | S )NzNumber of scatterers:)rx  zAt special positions:)ÚfÚprefix)	r{  r|  r~  r)   rL   rº   r   r<   Úshow_summary)r   rë  rì  r    r    r!   rí    s     zstructure.show_summaryc             C   sX   |d krt j}td|d |  ¡ }|r4| |  ¡ ¡}x|D ]}|j||  ¡ d q:W | S )NzLLabel, Scattering, Multiplicity, Coordinates, Occupancy, Uiso, Ustar as Uiso)rx  )rë  r:   )r{  r|  r~  r)   rz   rº   Úshowr:   )r   rë  Zspecial_positions_onlyr)   r   r    r    r!   Úshow_scatterersŠ  s     
zstructure.show_scatterersc          	   C   s.   | j j| |  ¡  ¡ |||  ¡  ¡ ||d d S )N)r-   Úsite_labelsÚsites_frac_originalÚsites_cart_originalÚsites_frac_exactr„  rì  )r7   Úshow_special_position_shiftsr)   Úextract_labelsr'  )r   rñ  rò  r„  rì  r    r    r!   rô  •  s    

z&structure.show_special_position_shiftsçíµ ÷Æ°>c             C   s  |   ¡  ¡ |  ¡  ¡ krdS |  ¡  | ¡ ¡}t|  ¡ | ¡ |ƒ}t|  ¡ | ¡ |ƒ}t|   ¡  ¡ |  ¡  ¡ |ƒ}t|   ¡  ¡ |  ¡  ¡ ƒ}|  	¡  
¡ }| 	¡  
¡ }	d}
x.t||	ƒD ] \}}|
t| ¡ | ¡ |ƒM }
q´W tt||||||
gƒƒ}t|ƒdko|d S )zA
    Check if similar. Can be endlessly fortified as needed.
    FTr'   r   )r)   rL   r(   Úis_similar_symmetryr   re   r•   rp   r,  r5   r¿   r   Ú
parametersr  ÚsetrÀ   )r   r9   ÚepsÚf1Úf2Úf3Úf4Zf5Zsr1Zsr2Zf6r}   r~   rë  r    r    r!   Ú
is_similar£  s"     zstructure.is_similarc             C   s6   |d krt j| j|  ¡ dS t j| j|  ¡ |dS d S )N)r)   r:   )r)   r:   Úu_cart_tolerance)r   r}  r6   r:   )r   r   r    r    r!   r}  ¸  s    z structure.is_positive_definite_ugR¸…ë?@g      Ð?c             C   s.   ||k st ‚tj| j|  ¡ | j|||d dS )zŒ
    Clean up atomic displacements so they fall within a sensible range (this
    is especially important when writing out PDB format).
    )r)   r:   r*   Úu_minÚu_maxÚanisotropy_minN)r,   r   Útidy_usr6   r:   r7   )r   r  r  r  r    r    r!   r  Ã  s    zstructure.tidy_usc             C   sd   ||g  d ¡dkst‚|d kr(t |¡}|d krHtj| j|  ¡ |d ntj| j|  ¡ ||d d S )Nr'   )r)   r:   Úu_shift)r)   r:   r  rP   )r   r,   r
   rR   r   Úshift_usr6   r:   )r   r  Zb_shiftrP   r    r    r!   r  Ò  s    

zstructure.shift_usc             C   s0   |d k	rt j| j||d nt j| j|d d S )N)r)   Úq_shiftrP   )r)   r  )r   Úshift_occupanciesr6   )r   r  rP   r    r    r!   r  á  s    
zstructure.shift_occupanciesc             C   s   t j| j| jd d S )N)r*   r)   )r   Úapply_symmetry_sitesr7   r6   )r   r    r    r!   r	  ê  s    zstructure.apply_symmetry_sitesc             C   s   t j| j| j|  ¡ d d S )N)r*   r)   rD   )r   Úapply_symmetry_u_starsr7   r6   rD   )r   r    r    r!   r
  ï  s    z structure.apply_symmetry_u_starsc             C   s$   | j | j| j |¡|  ¡ d d S )N)r¸  rD   )r6   r»  r7   r»   rD   )r   Zi_scattererr    r    r!   Úre_apply_symmetryõ  s    

zstructure.re_apply_symmetryc             C   sP   xJ|   ¡ D ]>}| j |¡ ¡ }t | ¡  ¡ ¡}t || ¡| j	||< q
W d S )N)
rº   r7   r»   rð   r   Úsqrr_   Ú	as_doubleÚrowÚelems)r   Zd_target_d_siter`   rð   r_   r    r    r!   Ú*apply_special_position_ops_d_target_d_siteú  s    z4structure.apply_special_position_ops_d_target_d_sitec             C   s@   t t tj | ¡¡| j| jd}|  ¡  ¡ |_	|  
¡  ¡ |_|S )N)r5   r4   )r&   r   r-   r<   Úcell_equivalent_p1r1   r4   r)   r@   r6   r*   r7   )r   Znew_structurer    r    r!   Úasymmetric_unit_in_p1   s    
zstructure.asymmetric_unit_in_p1c             C   sJ   t |tƒrt |¡}ttj | |¡tj| j	|d| j
j|d| j| jdS )N)r)   Úcb_op)r  )r-   r)   r*   r5   r4   )rµ   rJ   r	   Úchange_of_basis_opr&   r   r-   Úchange_basisr   r6   r7   r1   r4   )r   r  r    r    r!   r  
  s    

zstructure.change_basisc             C   s   |   ¡  ¡  ¡ }|  |¡S )N)r;   r±  Úchange_of_hand_opr  )r   Zch_opr    r    r!   Úchange_hand  s    zstructure.change_handc          	   C   sN   t t tj | ¡¡tj|  ¡ |  ¡ | j	| j
|d| j| jd}|rJ| ¡ }|S )a4  Get the current structure expanded into spacegroup P1.
    This turns all symmetry induced scatterers into independent
    individual scatterers. The expanded structure may have sites
    with negative or > 1.0 coordinates. Use '.sites_mod_positive()'
    or '.sites_mod_short()' on the result, or alternatively
    set sites_mod_positive to 'True' in case you want to change this behaviour.

    :param append_number_to_labels: If set to 'True' scatterers generated from     symmetry will be labelled with a numerical suffix
    :type append_number_to_labels: boolean
    :param sites_mod_positive: If set to 'True' xyz coordinates of the     scatterers will be kept inside [0,1[
    :type sites_mod_positive: boolean

    :returns: a new instance of the structure expanded into P1
    :rtype: cctbx.xray.structure
    )r:   rœ   r)   r*   Úappend_number_to_labels)r-   r)   r5   r4   )r&   r   r-   r<   r  r   Úexpand_to_p1r:   rœ   r6   r7   r1   r4   Úsites_mod_positive)r   r  r  rŽ   r    r    r!   r    s    
zstructure.expand_to_p1c             C   s   t | |  ¡  ¡ | j| jdS )zöGet the current structure converted into a structure with x,y,z of all
    scatterers in the interval [0,1[

    :returns: the same instance of the structure with only posive coordinates     of its scatterers
    :rtype: cctbx.xray.structure
    )r-   r)   r5   r4   )r&   r)   r  r1   r4   )r   r    r    r!   r  =  s
    
zstructure.sites_mod_positivec             C   s   t | |  ¡  ¡ | j| jdS )zûGet the current structure converted into a structure with short
    coordinates vectors of all scatterers

    :returns: the same instance of the structure with only short coordinates     vectors of its scatterers
    :rtype: cctbx.xray.structure
    )r-   r)   r5   r4   )r&   r)   Úsites_mod_shortr1   r4   )r   r    r    r!   r  K  s
    
zstructure.sites_mod_shortc             C   sD   |   ¡  ¡ }| | ¡ | ¡ |r(d }n| j}t| ||| j| jdS )N)r-   r)   r*   r5   r4   )r)   r@   rg   r'  r7   r&   r1   r4   )r   Úshiftrr  Úshifted_scatterersr*   r    r    r!   Úapply_shiftY  s    zstructure.apply_shiftçš™™™™™É?c             C   s>   t  t  |  ¡  ¡ d ¡d d | ¡}|  |  ¡ j|d¡S )Nr¸   r“   r'   )rk   )r   ru   rZ   r)   rL   r  r:   rl   )r   Zmax_shift_cartÚshiftsr    r    r!   Úrandom_shift_sitesg  s    $zstructure.random_shift_sitesrç   c             C   sT   |dkst ‚|dkst ‚tj|  ¡  ¡ |d}t| | j |¡| j |¡| j	| j
dS )N)rç   )FT)rz  Úreverse)r-   r)   r*   r5   r4   )r,   r   Úsort_permutationr)   rp   r&   r6   rz   r7   r1   r4   )r   Úby_valuer"  Úpr    r    r!   Úsortl  s    


zstructure.sortc             C   sD   ddl m} g }x&|  ¡ D ]}| | |j|j¡¡ qW | | |¡S )Nr   )Úeuclidean_model_matching)Úcctbxr'  r)   rŠ   ÚpositionrO  rï   Úmodel)r   ZemmaÚ	positionsr¼  r    r    r!   Úas_emma_modely  s
    zstructure.as_emma_modelc             C   sh   ddl m} t ¡ }xN|  ¡ D ]B}tjj|jddd}|d krLt	d|j ƒ‚| 
| |¡ ¡ ¡ qW |S )Nr   )rÞ   T)rO  r  r  zUnknown atomic weight: )rá   rÞ   r   rN   r)   r   r’  r—  rÔ   rW   rŠ   r   rß   )r   rÞ   rŽ   r¼  r¡  r    r    r!   ro  €  s    zstructure.atomic_weightsc             C   s    |d kr|   ¡ }|  ¡ j|dS )N)Úweights)ro  rk   Úmean_weighted)r   ro  r    r    r!   Úcenter_of_massŒ  s    zstructure.center_of_massc             C   s$   |d kr|   ¡ }tjj|  ¡ |dS )N)Úpointsr-  )ro  Úscitbxr  Úprincipal_axes_of_inertiark   )r   ro  r    r    r!   r2  ‘  s
    z#structure.principal_axes_of_inertiac             C   sN   | j  ¡ | ¡ kst‚|d k	r6| j j|  ¡ ||d n| j j|  ¡ |d d S )N)r:   Úu_cartrP   )r:   r3  )r6   rL   r,   Ú
set_u_cartr:   )r   r3  rP   r    r    r!   r4  ˜  s    
zstructure.set_u_cartc             C   sÒ  |d krt j}d}d}d}d}d}d}d}d}	d}
d}d}xÎ|  ¡ D ]Â}|j}| ¡ r^|d7 }| ¡ | ¡  }}|r‚|r‚|d7 }n$|r|d7 }n|rž|d7 }n|d7 }| ¡ r¶|d7 }| ¡ rÆ|d7 }| 	¡ rÖ|	d7 }	| 
¡ ræ|
d7 }
| ¡ rö|d7 }| ¡ rD|d7 }qDW td||d |dkr0td||d |dkrHtd||d td||d td||d td	||d td
||d td|	|d td|
|d td||d td||d td|  ¡  ¡ |d d S )Nr   r'   zn_use            = )rx  zn_use_u_none     = zn_use_u_both     = zn_use_u_iso      = zn_use_u_aniso    = zn_grad_site      = zn_grad_u_iso     = zn_grad_u_aniso   = zn_grad_occupancy = zn_grad_fp        = zn_grad_fdp       = ztotal number of scatterers = )r{  r|  r)   r…   r†   r‡   r‰   Ú	grad_siteÚ
grad_u_isoÚgrad_u_anisoÚgrad_occupancyÚgrad_fpÚgrad_fdpr~  rL   )r   r„  Zn_useZn_use_u_bothZn_use_u_isoZn_use_u_anisoZn_use_u_noneZn_grad_siteÚn_grad_u_isoÚn_grad_u_anisoZn_grad_occupancyZ	n_grad_fpZ
n_grad_fdpr¼  r…   r`   Úar    r    r!   Úshow_scatterer_flags_summary¢  sf       
 
 
      

z&structure.show_scatterer_flags_summaryc             C   s   t  |  ¡ ¡S )N)r   Úshared_scatterer_flagsr)   )r   r    r    r!   Úscatterer_flagsÍ  s    zstructure.scatterer_flagsc             C   s   |  |  ¡ ¡ d S )N)Ú	assign_tor)   )r   r@  r    r    r!   Úset_scatterer_flagsÐ  s    zstructure.set_scatterer_flagsc             C   s  d}|r|   ¡ }nd }xæt|  ¡ ƒD ]Ö\}}|j}|d kr@d }n| |¡}| ¡ rVd }| ¡ r€|d krp|d7 }n|| ¡  ¡ 7 }| 	¡ r˜| 
¡ r˜|d7 }| ¡ rÊ| ¡ rÊ|d krº|d7 }n|| ¡  ¡ 7 }| ¡ rÚ|d7 }| ¡ rê|d7 }| ¡ r$|d7 }q$W |S )Nr   r¸   r'   r„   )r*   r¥   r)   r…   r»   rý   r5  r¼   r½   r6  r‡   r7  r‰   Úadp_constraintsr8  r9  r:  )r   Z%considering_site_symmetry_constraintsrŽ   Zsstabr  r   r…   rü   r    r    r!   Ún_parametersÓ  s<    


 
   zstructure.n_parametersc             C   s   |   ¡  ¡ S )N)r)   r;  )r   r    r    r!   r;  ô  s    zstructure.n_grad_u_isoc             C   s   |   ¡  ¡ S )N)r)   r<  )r   r    r    r!   r<  ÷  s    zstructure.n_grad_u_anisoc             C   s   t j |  ¡ ¡S )N)r(  rŒ  Úparameter_mapr)   )r   r    r    r!   rE  ú  s    zstructure.parameter_mapc             C   s´   |   ¡ }|j}|j}xš|  ¡ D ]Ž}|dd„ ||jƒD ƒƒ|_|jdkrbt tdt 	|j¡ ƒ¡|_td|j
 ƒ|_
|jdkrdd„ t ||j¡D ƒ}t |dd„ |D ƒ¡|_qW d S )	Nc             S   s   g | ]}t d | ƒ‘qS )z%8.3f)r[   )r«   r`   r    r    r!   r­     s    z>structure.truncate_at_pdb_format_precision.<locals>.<listcomp>g      ð¿z%6.2fz%5.2f)r  r  r  r  r  r  c             S   s   g | ]}t |d  ƒ‘qS )i'  )r—   )r«   r`   r    r    r!   r­     s    c             S   s   g | ]}t |ƒd  ‘qS )i'  )r[   )r«   r`   r    r    r!   r­     s    )r:   rl   rí   r)   rï   rˆ   r
   rR   r[   r–   rç   r‹   Úu_star_as_u_cartÚu_cart_as_u_star)r   ÚucZfraZortr   Zu_pdbr    r    r!   Ú truncate_at_pdb_format_precisioný  s    

z*structure.truncate_at_pdb_format_precisionc          
   C   s.   t j|  ¡ |  ¡ |  ¡ |  ¡ |  ¡ |||dS )N)r:   rœ   r)   r5   r*   Úmiller_indicesÚda_dbÚdaa_dbb_dab)r   Ú:structure_factors_curvatures_simple_grads_and_curvs_targetr:   rœ   r)   r5   r*   )r   rJ  rK  rL  r    r    r!   Úgrads_and_curvs_target_simple
  s    z'structure.grads_and_curvs_target_simplec             C   s6   |r
d }n|   ¡ }|j||  ¡  ¡ ||  ¡ |  ¡ dS )N)rë  rð  r*   re   r:   )r*   rî  r)   rõ  re   r:   )r   Úpair_sym_tableZis_full_connectivityr„  r*   r    r    r!   Úpair_sym_table_show  s    
zstructure.pair_sym_table_showc          
   C   s.   |j |  ¡ |  ¡ |  ¡  ¡ |  ¡ ||||dS )N)r:   r*   rð  re   Úshow_cartesianÚskip_j_seq_less_than_i_seqÚskip_sym_equivr„  )Úshow_distancesr:   r*   r)   rõ  re   )r   rO  rQ  rR  rS  r„  r    r    r!   Úpair_sym_table_show_distances$  s    
z'structure.pair_sym_table_show_distancesc             C   s*   t jj| ||d}tj|| j| jd |S )N)rÐ  Úasu_is_inside_epsilon)rÑ  r)   r*   )r   r<   rÑ  r   Úasu_mappings_processr6   r7   )r   rÐ  rV  rŽ   r    r    r!   rÑ  4  s    
zstructure.asu_mappingsrU   c             C   sT   |d k	s|d k	st ‚|d kr |}| j||d}tj|d}|d k	rP|j||d |S )N)rÐ  rV  )rÑ  )rÒ  Úmin_cubicle_edge)r,   rÑ  r   Úpair_asu_tableÚadd_all_pairs)r   rÒ  Úasu_mappings_buffer_thicknessrV  rX  rÑ  rY  r    r    r!   rY  >  s    zstructure.pair_asu_tablec	       	      C   sP   ||g  d ¡dkst‚|d kr0| j||||d}|j|  ¡  ¡ |  ¡ |||dS )Nr'   )rÒ  r[  rV  rX  )rð  re   rQ  Úkeep_pair_asu_tabler„  )r   r,   rY  rT  r)   rõ  re   )	r   rÒ  r[  rV  rX  rY  rQ  r\  r„  r    r    r!   rT  Q  s    	
zstructure.show_distancesc             C   sL   ||g  d ¡dkst‚|d kr.| j|||d}|j|  ¡  ¡ |  ¡ ||dS )Nr'   )rÒ  r[  rV  )rð  re   r\  r„  )r   r,   rY  Úshow_anglesr)   rõ  re   )r   rÒ  r[  rV  rY  r\  r„  r    r    r!   r]  h  s    
zstructure.show_anglesç333333û?éª   c	       	      C   s8   |d kr| j |||d}|j|  ¡  ¡ |  ¡ |||dS )N)rÒ  r[  rV  )rð  re   Úmax_dÚ	max_angler„  )rY  Úshow_dihedral_anglesr)   rõ  re   )	r   rÒ  r`  ra  r[  rV  rY  r\  r„  r    r    r!   rb  {  s    	
zstructure.show_dihedral_anglesc             C   s   t | ||dS )N)r&   Úbond_sym_tableÚconserve_angles)Úconservative_pair_proxies)r   rc  rd  r    r    r!   re    s    z#structure.conservative_pair_proxiesc             C   s   |  ¡ |   ¡  S )N)rk   )r   r9   r    r    r!   Údifference_vectors_cart–  s    z!structure.difference_vectors_cartc             C   s   |   ¡  |  ¡ ¡S )N)rk   rò   )r   r9   r    r    r!   rò   ™  s    zstructure.rms_differencec                sX   G ‡ fdd„dt ƒ}|d k	r4| ¡ | j ¡ ksFt‚nt | j ¡ d¡}|| ||d}|S )Nc                   s   e Zd Z‡ fdd„ZdS )zQstructure.closest_distances.<locals>.map_next_to_model_and_find_closest_distancesc                sŠ  |j ˆ d}|j|| ¡ d tj|ˆ d}| ¡  ¡ }| ¡ }t 	| ¡ ˆ d d ¡}t 
| ¡ d¡}	xÜ|D ]Ô}
|
j|k rÈ|
j|k rˆqn| |
¡}| |
¡}| ¡  |¡}|
j| }|||  }|
j}nJ|
j|krÔqn| |
¡}| |
¡}| ¡  |¡}|
j| }|||  }|
j}|| rn|| |
jkrn|
j||< |||< ||	|< qnW |ˆ d k| _|| _t |¡ | jd¡| _| | jd¡| _|	| _d S )N)rÐ  )rC   )rÑ  rÒ  r“   r'   r  )rÑ  Úprocess_sites_fracrC   r   rÓ  r)   rL   r@   r   rN   r—   r”   Új_seqÚget_rt_mx_iÚget_rt_mx_jÚinverseÚmultiplyÚdist_sqZremove_selectionre   r{   rf   Zsmallest_distancesÚsmallest_distances_sqÚi_seqs)r   rÞ  re   Úuse_selectionrÑ  Úpair_generatorZn_xrayZnew_sites_fracrn  ro  ÚpairZrt_mx_iÚrt_mx_jÚrt_mx_jiZi_seq_new_site_fracZnew_site_fracZjnZrt_mx_ij)rÒ  r    r!   r"   ž  sR    




 



 



zZstructure.closest_distances.<locals>.map_next_to_model_and_find_closest_distances.__init__N)r#   r$   r%   r"   r    )rÒ  r    r!   Ú,map_next_to_model_and_find_closest_distances  s   ru  T)rÞ  re   rp  )ÚobjectrL   r6   r,   r   rK   )r   re   rÒ  rp  ru  rŽ   r    )rÒ  r!   Úclosest_distancesœ  s    .zstructure.closest_distancesc                sn   |   ¡ }| ¡ }‡ fdd„t|| ¡ ƒD ƒ}|‡ fdd„|D ƒ7 }ttj|dd|  ¡ | jd}| 	|¡ |S )Nc                s    g | ]\}}d ˆ  | | ‘qS )r“   r    )r«   r`   r=  )Úbuffer_sizer    r!   r­   ×  s    zOstructure.orthorhombic_unit_cell_around_centered_scatterers.<locals>.<listcomp>c                s   g | ]}ˆ | ‘qS r    r    )r«   r`   )rx  r    r!   r­   Ø  s    ÚP1)r:   Úspace_group_symbol)r(   r)   r4   )
rk   rY   r   rX   r&   r   r<   r)   r4   r*  )r   rx  rk   Úsites_cart_minÚabcrŽ   r    )rx  r!   Ú1orthorhombic_unit_cell_around_centered_scatterersÔ  s    

z;structure.orthorhombic_unit_cell_around_centered_scatterersc                s†   |   ¡ }| ¡ }dd„ t|| ¡ ƒD ƒ}t|ƒd|  ‰ |‡ fdd„t||ƒD ƒ7 }ttjˆ ˆ ˆ gdd|  ¡ | jd}| 	|¡ |S )Nc             S   s   g | ]\}}|| ‘qS r    r    )r«   r`   r=  r    r    r!   r­   å  s    zHstructure.cubic_unit_cell_around_centered_scatterers.<locals>.<listcomp>r“   c                s    g | ]\}}ˆ | d  | ‘qS )r“   r    )r«   r`   rQ   )r=  r    r!   r­   ç  s    ry  )r:   rz  )r(   r)   r4   )
rk   rY   r   rX   r&   r   r<   r)   r4   r*  )r   rx  rk   r{  ÚspanrŽ   r    )r=  r!   Ú*cubic_unit_cell_around_centered_scatterersâ  s    

z4structure.cubic_unit_cell_around_centered_scatterersÚglobalÚmmCIFc             C   sB   |d krt j}dd l}|jj ¡ }| j|d||< t||d d S )Nr   )Úformat)rx  )r{  r|  Ú	iotbx.cifÚcifr*  Úas_cif_blockr~  )r   r„  Ú	data_namer‚  Úiotbxr„  r    r    r!   Úas_cif_simpleñ  s     zstructure.as_cif_simplec       &         sj  ddl m}m} |  ¡ j||d}|  ¡ }|  ¡ }|d k	rl|  ¡ }	| ¡ }
t	 
t	 | ¡ ¡¡}t | ¡ ¡}d‰ |jdd}xÄt|ƒD ]¶\}‰d  } }}|d k	r²|	| }ˆj ¡ r|jdkrg }x6tdƒD ]*}| tˆj| t |
|j|  ¡ƒ¡ qÖW ˆj ¡ r4|jdkr4tˆjt |
|j ¡ƒ}ˆj ¡ sLˆj ¡ r²ˆj ¡ rvtˆjt t  |||	¡¡ƒ}n<t !|||	¡ "¡ }|t #|¡  $|¡}tˆ %|¡t |¡ƒ}|d krÔ‡ ‡fdd	„tdƒD ƒ}|d krèˆ ˆj }|d kr ˆ ˆ %|¡ }ˆj &¡ rd
}nd}| 'ˆj(ˆj)|d |d |d |||f¡ qˆW | *|¡ | +| ,¡ ¡}| -¡ rft.| /¡ ƒ}|jdd}g }x|D ]
‰ˆj0r¢| ˆ¡ t1 2|ˆj3¡‰|d k	rjˆj(g}|	| 4ˆj(¡ j5}|dkrH|
||d … | }xttdƒD ]F}|| dkr.| tˆ| t || ¡ƒ¡ n| ˆ ˆ|  ¡ qüW n ˆj(g‡ ‡fdd	„tdƒD ƒ }n ˆj(g‡ ‡fdd	„tdƒD ƒ }| '|¡ qŠW | *|¡ |rTddl6m7} ddl6m8} dg}dg} xDt	 9| :¡ ¡D ]2}| d|d d |d d |d d f ¡ qÞW xNt	 9| :¡ ¡D ]<}|  d|d d |d d |d d |d d f ¡ q$W |j|d}!|j| d}"xÂ|D ]º‰ˆj(g}#ˆj(g}$xŽtˆj0 ;¡ ƒD ]|\}}%|d k	r |	| 4ˆj(¡ j5}|dkr |
|d |d d … }t|%t || ¡ƒ}%|dk r|# |%¡ n
|$ |%¡ q¦W |! '|#¡ |" '|$¡ q‚W | *|!¡ | *|"¡ | *|| |d¡ |S )Nr   )Úatom_type_cif_loopr*  )r‚  Úcell_covariance_matrixz%.6f)Ú_atom_site_labelÚ_atom_site_type_symbolÚ_atom_site_fract_xZ_atom_site_fract_yZ_atom_site_fract_zÚ_atom_site_U_iso_or_equivÚ_atom_site_adp_typeÚ_atom_site_occupancy)Úheaderr¸   c                s   g | ]}ˆ ˆj |  ‘qS r    )rï   )r«   r`   )Úfmtr   r    r!   r­   0	  s    z*structure.as_cif_block.<locals>.<listcomp>ZUaniZUisor'   r“   )Ú_atom_site_aniso_labelZ_atom_site_aniso_U_11Z_atom_site_aniso_U_22Z_atom_site_aniso_U_33Z_atom_site_aniso_U_12Z_atom_site_aniso_U_13Z_atom_site_aniso_U_23r  r„   c                s   g | ]}ˆ ˆ|  ‘qS r    r    )r«   r`   )r’  Úu_cifr    r!   r­   [	  s    c                s   g | ]}ˆ ˆ|  ‘qS r    r    )r«   r`   )r’  r”  r    r!   r­   ]	  s    )Úrank_3_tensor_constraints)Úrank_4_tensor_constraintsZ_atom_site_anharm_GC_C_labelZ_atom_site_anharm_GC_D_labelz_atom_site_anharm_GC_C_%s%s%sz_atom_site_anharm_GC_D_%s%s%s%sé   rë   )r‚  )<rƒ  r‰  r*  r(   r…  r)   r:   rE  Úmatrix_packed_u_diagonalr   Úpow2rN   Úu_star_to_u_cif_linear_mapr   r  Úu_star_to_u_iso_linear_formÚloopr¥   r…   r5  rï   r   rŠ   Úformat_float_with_sur  r{   r8  rç   r6  r7  rˆ   r   Úvariance_for_u_isoÚ%extract_covariance_matrix_for_u_anisoÚmatrix_packed_u_as_symmetricr  r|   Úu_iso_or_equivr‰   Úadd_rowrO  rÔ   Úadd_looprz   r)  rL   r  rõ  Úanharmonic_adpr
   Úu_star_as_u_cifr‹   ÚindexÚu_anisoÚcctbx.sgtbxr•  r–  Úrowsr¹   rz  )&r   Úcovariance_matrixrŠ  r‚  r‰  r*  Úcs_cif_blockr)   rH  Z	param_mapZcovariance_diagonalZu_star_to_u_cif_linear_map_pow2r›  Úatom_site_loopr”   rï   Zoccur¡  Úparamsr`   ÚcovÚvarÚadp_typeZaniso_scatterersrd  Ú
aniso_loopZanharmonic_scatterersr  ÚidxZt3cZt4cZC_headerZD_headerZC_loopZD_loopZC_rowZD_rowÚdr    )r’  r   r”  r!   r…  ø  sÐ    










" 
2<






zstructure.as_cif_blockc             C   s"   dd l }|jjj| |||||dS )Nr   )r   ÚremarkÚremarksÚfractional_coordinatesrR  Úconnect)Ziotbx.pdb.xray_structureÚpdbrÞ  Úas_pdb_file)r   r´  rµ  r¶  rR  r·  r‡  r    r    r!   r¹  	  s    zstructure.as_pdb_filec             O   s   dd l }|jj||ŽS )Nr   )Úiotbx.shelxÚshelxZ_cctbx_xray_structure_from)ÚclsÚargsÚkwdsr‡  r    r    r!   Ú
from_shelxŽ	  s    zstructure.from_shelxc             C   sZ   dd l }ddl m} |jj||||jd}t|jƒrN|d k	rF|j| S |jS ntdƒ‚d S )Nr   )Úbuilders)Úfile_objectÚ	file_pathÚdata_block_nameÚdata_structure_builderz8Could not extract an xray.structure from the given input)rƒ  rÀ  r„  Úcctbx_data_structures_from_cifÚcrystal_structure_builderrÀ   Úxray_structuresr   )r¼  rÁ  rÂ  rÃ  r‡  rÀ  rŽ   r    r    r!   Úfrom_cif“	  s    


zstructure.from_cifc                s   t ‡ fdd„|  ¡ D ƒƒS )z4 The content of the unit cell as a chemical formula c                s&   g | ]}ˆ r|j ˆ kr|j |jf‘qS r    )rÔ   rÕ   )r«   r_   )Úomitr    r!   r­   ¥	  s   z/structure.unit_cell_content.<locals>.<listcomp>)ÚdictrÝ   )r   rÉ  r    )rÉ  r!   Úunit_cell_content£	  s    zstructure.unit_cell_contentc                sì   g ‰d‰d‰ ‡ ‡fdd„}t ƒ ‰‡‡‡fdd„‰x¶|  ¡ D ]ª‰ˆj ¡  dd¡ ¡ ‰|ˆƒ}ˆˆkrt|rtˆˆd	 q:‡‡‡fd
d„}‡‡‡fdd„}‡‡‡fdd„}|rÌ|ddƒr´q:|ddƒrÀq:|ddƒrÌq:|ƒ rÔq:|ƒ rÜq:tdƒ‚q:W ˆS )NÚABCDEFGHIJKLMNOPQRSTUVWXYZÚ
0123456789c                s^   t | ƒdkrdS t | ƒdkr dS | d ˆkr0dS x(| dd … D ]}|ˆkr>|ˆ kr>dS q>W dS )Nr   Fé   r'   T)rÀ   )ÚlblrÃ   )Údigitsr.  r    r!   Úis_useful_label­	  s       zRstructure.make_scatterer_labels_shelx_compatible_in_place.<locals>.is_useful_labelc                s.   ˆj | kr ˆ ˆj | f¡ | ˆ_ ˆ  | ¡ d S )N)rO  rŠ   Úadd)rO  )Úlbl_setrŽ   r   r    r!   Úreset·	  s    
zHstructure.make_scatterer_labels_shelx_compatible_in_place.<locals>.resetr9  rÊ   )rO  c                sN   xHt d|ƒD ]:}| | }ˆ d dt|ƒ … | }|ˆkrˆ|d dS qW dS )Nr'   rÎ  )rO  TF)r   rÀ   )r’  r…  r`   rQ   Útrial)rÏ  rÓ  rÔ  r    r!   Úfind_tail_replacementÂ	  s    
zXstructure.make_scatterer_labels_shelx_compatible_in_place.<locals>.find_tail_replacementc                 sž   ddl m}  | ˆjdd\}}t|ƒdkr.dS t|ƒdks>t‚t|ƒdkrTd\}}nd\}}| ¡ }x4td|ƒD ]&}|||  }|ˆ krpˆ|d	 d
S qpW dS )Nr   )Úget_element_and_charge_symbolsF)rÔ   r  r“   r'   )z%03diè  )z%02déd   )rO  T)Úcctbx.eltbx.xray_scatteringr×  rÔ   rÀ   r,   r.  r   )r×  Úer¬   r’  r…  r`   rÕ  )rÓ  rÔ  r   r    r!   Ú&find_replacement_using_scattering_typeÊ	  s"      

zistructure.make_scatterer_labels_shelx_compatible_in_place.<locals>.find_replacement_using_scattering_typec                 sH   xBˆD ]:} x4t ddƒD ]&}| d|  }|ˆ krˆ|d dS qW qW dS )Nr'   iè  z%03d)rO  TF)r   )rÃ   r`   rÕ  )rÓ  rÔ  r.  r    r!   Úfind_complete_replacementÚ	  s    

z\structure.make_scatterer_labels_shelx_compatible_in_place.<locals>.find_complete_replacementz%drë   z%02drØ  z%03diè  z7Unable to find unused SHELX-compatible scatterer label.)rù  r)   rO  r-  Úreplacer.  rW   )r   rÑ  Zlbl_is_usefulrÖ  rÛ  rÜ  r    )rÐ  rÏ  rÓ  rÔ  rŽ   r   r.  r!   Ú/make_scatterer_labels_shelx_compatible_in_place©	  s8    	
 
 
   
z9structure.make_scatterer_labels_shelx_compatible_in_placec             C   sd   |   ¡ | }|   ¡ | }|j ¡ r*|j}n|j}|j ¡ rB|j}n|j}tj|||j|j|  ¡ dS )z
    For a pair of scatterers, calculates their overlap given the coordinates
    and displacement parameters (using adptbx.intersection).
    )Úu_1Úu_2Úsite_1Úsite_2r:   )	r)   r…   r‰   r‹   rˆ   r
   Úintersectionrï   r:   )r   r”   rh  Zsc1Zsc2Úu1Úu2r    r    r!   Úintersection_of_scatterersì	  s    

z$structure.intersection_of_scatterers)NNNFNNN)NNN)NNN)N)N)N)r   r   r   )N)N)N)N)N)NNr   r‘   Fr’   N)r‘   )N)N)N)N)N)N)N)F)NNNFN)N)FFF)NT)N)N)rÊ   NF)NNNNF)T)Tr«  )F)NN)NF)r×  )NNNFNNNN)rÊ   )NrÊ   )NF)NNNrÊ   )rö  )N)NNN)N)FF)F)r  )rç   F)N)N)N)N)F)FN)FFFN)N)NNNrU   )NNNrU   NFFN)NNNNFN)Nr^  r_  NNNFN)N)Nr€  r  )NNr  )NNN)N)˜r#   r$   r%   Ú__doc__r"   r.   r(   r>   r/   rB   r   rF   r)   r+   rM   rT   rd   rj   rm   rn   rs   rt   ry   r   r€   r   rƒ   r   r¢   r£   r§   r©   r±   r´   rq   r¯   r³   r¾   rÈ   rÉ   rÓ   rÝ   rå   rê   rù   r"  r$  r%  r&  re   r‡   r‰   rñ   rk   r*  r0  r¤   r•   r1  r2  r5  r8  rS  r\  r]  r_  r`  rc  re  rj  rl  rs  rq  rt  ru  rˆ  r*   rº   r5   rª  r®  r°  rµ  rz   r·  r½  r2   rÀ  rÏ  rÖ  rØ  r   rç  rí  rï  rô  rÿ  r}  r
   rR   r  r  r  r	  r
  r  r  r  r  r  r  r  r  r  r!  r&  r,  ro  r/  r2  r4  r>  r@  rB  rD  r;  r<  rE  rI  rN  rP  rU  rÑ  rY  rT  r]  rb  re  rf  rò   rw  r}  r  rˆ  r…  r¹  Úclassmethodr¿  rÈ  rË  rÞ  ræ  r    r    r    r!   r&   +   s¼        

 		


$    Qj  @
+
 3    P
 
  !

      9	   

	
 "
+!                          8  
Cr&   c               @   s   e Zd Zdd„ ZdS )re  c       	      C   s–   ddl m} tjtj|| ¡  ¡ | ¡ ddd}|r>|d9 }|j	|d}tj
|d}|j|d	 |j|d
| _|s|d | _n| ¡ }|j|d
| _d S )Nr   )Úgeometry_restraints)rO  Úorthogonalization_matrixre   r'   )rO   Údefaultr“   )rÐ  )rÑ  )Z	sym_table)rY  )r(  ré  r   Úmax_defaultr   Úget_distancesr:   rê  re   rÑ  rY  Úadd_pair_sym_tableZbond_sorted_asu_proxiesÚbondr	  Úangle_pair_asu_table)	r   r&   rc  rd  ré  rÐ  rÑ  Zbond_pair_asu_tablerð  r    r    r!   r"   
  s&    

 
z"conservative_pair_proxies.__init__N)r#   r$   r%   r"   r    r    r    r!   re  
  s   re  c               @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú meaningful_site_cart_differencesaw   Differences between the Cartesian coordinates of corresponding sites
  in two structures, cancelling continuous origin shifts if any.

  This is especially useful to compare a refined
  structure to a reference structure as the former may have drifted along
  a continuous shift direction during refinement, therefore spoiling
  a naive comparison of corresponding sites.
  c                s¬  dd„ ˆ  ¡ D ƒ| _ˆ ¡ | ¡   | _‰ ˆ ¡ | ¡ kr¨t ˆ ¡ ¡jdd}| ¡ r¨‡fdd„| 	¡ D ƒ}t
|ƒdkrž|d  ¡ }| ¡ }| |¡}ndt
|ƒdkrä|d  ¡ }|d }|d| |¡ |   ¡ }| |¡}nt
|ƒd	krd
ddg\}}}‡ fdd„|||fD ƒ}	dd„ |	D ƒ}
t
|ƒdkrF|
d ddf}n8t
|ƒdkrh|
d |
d df}nt
|ƒd	kr~t|
ƒ}t |	d |	d |	d ¡| _|  j|8  _d S )Nc             S   s   g | ]
}|j ‘qS r    )rO  )r«   r   r    r    r!   r­   &
  s    z=meaningful_site_cart_differences.__init__.<locals>.<listcomp>F)Zdiscretec                s"   g | ]}t  ˆ  ¡  |j¡¡‘qS r    )r   rî   r:   rí   r  )r«   Úvm)Úxs1r    r!   r­   ,
  s   r'   r   r“   r¸   )r'   r   r   )r   r'   r   )r   r   r'   c                s   g | ]}ˆ   |¡‘qS r    )r|   )r«   rÚ  )Úcanonical_deltar    r!   r­   9
  s    c             S   s   g | ]}t  |¡‘qS r    )r   r‚   )r«   r³  r    r    r!   r­   :
  s    )r)   rd  rk   Údeltarœ   r	   Ústructure_seminvariantsrz   rL   Úvectors_and_modulirÀ   r  Úorthor  r|   Útupler   ru   )r   ró  Zxs2Zssir   Ze0Úe1Úe2r  ÚdeltasZmeansZmeans_correctionr    )rô  ró  r!   r"   %
  s:    

z)meaningful_site_cart_differences.__init__c             C   s   t  | j ¡ ¡S )N)r   Úmax_absoluterõ  r  )r   r    r    r!   rý  D
  s    z-meaningful_site_cart_differences.max_absolutec             C   s6   x0t j | j| j¡D ]\}}td|f|  ƒ qW d S )Nz%6s: (%.6f, %.6f, %.6f))rÁ  rÂ  r   rd  rõ  r~  )r   rÏ  Údiffr    r    r!   rî  G
  s    z%meaningful_site_cart_differences.showN)r#   r$   r%   rç  r"   rý  rî  r    r    r    r!   rñ  
  s   rñ  )1Ú
__future__r   r   r   Ú
cctbx.xrayr   r   r(  r   r   r	   rÙ  r
   r   Úcctbx.array_familyr   Úscitbx.mathr1  r   r  Ú	itertoolsr   r{  r™   rÁ  Úlibtbx.utilsr   r   r   Úlibtbx.test_utilsr   Úlibtbxr   Zlibtbx.assert_utilsr   Úcctbx.eltbx.neutronr   r   r  r   Ú	six.movesr   r   rv  r   r-   r&   re  rñ  r    r    r    r!   Ú<module>   sb                      j