ó
ø™xTc           @   sŒ   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 e f d „  ƒ  YZ e e e d	 „ Z d
 S(   iÿÿÿÿ(   t   division(   t   matrix(   t	   unit_cell(   t   space_group(   t   space_group_symbols(   t   crystal_orientationt   crystal_modelc           B   s7  e  Z d  Z d! d! d! e d „ Z e d „  ƒ Z e d! d „ Z	 d „  Z
 d „  Z d „  Z d „  Z d „  Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z e d „ Z e d „ Z d „  Z d d „ Z d d d d d „ Z d „  Z d „  Z  d  „  Z! RS("   sÖ  Simple model for the crystal lattice geometry and symmetry

  A crystal is initialised from the elements of its real space axes
  a, b, and c. Space group information must also be provided, either
  in the form of a symbol, or an existing
  cctbx.sgtbx.space_group object. If space_group_symbol is provided,
  it is passed to the cctbx.sgtbx.space_group_symbols constructor.
  This accepts either extended Hermann Mauguin format, or Hall format
  with the prefix 'Hall:'. E.g.

  space_group_symbol = "P b a n:1"
      or
  space_group_symbol = "Hall:P 2 2 -1ab"

  Optionally the crystal mosaicity value may be set, with the deg
  parameter controlling whether this value is treated as being an
  angle in degrees or radians.c   	      C   s  | | g j  d  ƒ d k s! t ‚ | r? t t | ƒ ƒ |  _ n	 | |  _ | d  k	 rj |  j | d | ƒn	 d |  _ t j	 | ƒ } t j	 | ƒ } t j	 | ƒ } t j
 | j | j | j ƒ j ƒ  } |  j | | | ƒ |  j ƒ  | |  j j ƒ  |  _ |  j ƒ  d  S(   Ni   t   degg        (   t   countt   Nonet   AssertionErrort   SGR   t   _sgt   set_mosaicityt
   _mosaicityR   t   colt   sqrt   elemst   inverset   set_unit_cellt	   _update_Bt   _Bt   _Ut   reset_scan_points(	   t   selft   real_space_at   real_space_bt   real_space_ct   space_group_symbolR   t	   mosaicityR   t   A(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   __init__   s"    !		

c         C   s   |  j  S(   N(   t   _num_scan_points(   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   num_scan_pointsA   s    c         C   s�  | d  k r$ d d  l } | j } n  |  j ƒ  j ƒ  } t |  j ƒ  j ƒ  ƒ } |  j ƒ  j	 d d d t
 ƒ j ƒ  } |  j ƒ  j	 d d d t
 ƒ j ƒ  } |  j ƒ  |  j ƒ  j	 d d d t
 ƒ j ƒ  } d g }	 |	 j d d | ƒ |	 j d | ƒ |	 j d	 | d
 ƒ |	 j d | d ƒ |	 j d | d ƒ |	 j d | d
 ƒ |	 j d | d ƒ |	 j d | d ƒ |	 j d | d
 ƒ |	 j d | d ƒ |	 j d | d ƒ |  j d
 k r†|	 j d t |  j ƒ d ƒ | r†x�t |  j ƒ D]‰}
 |  j |
 ƒ } |  j |
 ƒ } |  j |
 ƒ } |  j |
 ƒ j ƒ  } | j	 d d d t
 ƒ j ƒ  } | j	 d d d t
 ƒ j ƒ  } | j	 d d d t
 ƒ j ƒ  } |	 j d |
 d ƒ |	 j d d | ƒ |	 j d	 | d
 ƒ |	 j d | d ƒ |	 j d | d ƒ |	 j d | d
 ƒ |	 j d | d ƒ |	 j d | d ƒ |	 j d | d
 ƒ |	 j d | d ƒ |	 j d | d ƒ qóWq†n  | d j |	 ƒ IJd  S(   Niÿÿÿÿt   formats   % 5.4ft   one_row_per_lines   Crystal:s       Unit cell: s*   (%5.3f, %5.3f, %5.3f, %5.3f, %5.3f, %5.3f)s       Space group: s       U matrix:  i    s                  i   i   s       B matrix:  s       A = UB:    s       A sampled at s    scan pointss     Scan point #%i:s   
(   R	   t   syst   stdoutt   get_unit_cellt
   parameterst   strt   get_space_groupt   infot   get_Ut   mathematica_formt   Truet
   splitlinest   get_Bt   appendR!   t   ranget   get_A_at_scan_pointt   get_B_at_scan_pointt   get_U_at_scan_pointt   get_unit_cell_at_scan_pointt   join(   R   t   show_scan_varyingt   outR$   t   uct   sgt   umatt   bmatt   amatt   msgt   iR   t   Bt   U(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   showE   sd    	c         C   sB   d d l  m } | ƒ  } |  j d | ƒ } | j d ƒ | j ƒ  S(   Niÿÿÿÿ(   t   StringIOR8   i    (   t	   cStringIORC   RB   t   seekt   read(   R   RC   t   sR>   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   __str__z   s
    	c      	   C   st   | j  ƒ  | j  ƒ  | j  ƒ  | j | d t ƒ| j | d t ƒ| j | d t ƒf } t | ƒ |  _ |  j ƒ  d  S(   NR   (   t   lengtht   angleR-   R   t   _ucR   (   R   R   R   R   t   cell(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR   �   s    			c         C   s%   |  j  | ƒ } t | ƒ } | j ƒ  S(   N(   R3   R   R   (   R   t   tR@   t   co(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR5   ‹   s    c         C   s%   t  j |  j j ƒ  ƒ j ƒ  |  _ d  S(   N(   R   R   RK   t   fractionalization_matrixt	   transposeR   (   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR   �   s    c         C   s)   | j  ƒ  s t ‚ | |  _ |  j ƒ  d  S(   N(   t   is_r3_rotation_matrixR
   R   R   (   R   RA   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   set_U“   s    	c         C   s   |  j  S(   N(   R   (   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR+   œ   s    c         C   s   |  j  S(   N(   R   (   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR/   Ÿ   s    c         C   sM   t  | t ƒ } | j ƒ  |  _ t j |  j j ƒ  ƒ j ƒ  |  _ |  j	 ƒ  d  S(   N(
   R   R-   R   RK   R   R   RO   RP   R   R   (   R   R@   RN   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   set_B¢   s    !c         C   s8   g  | D] } t  j | ƒ ^ q |  _ t | ƒ |  _ d S(   s¡  Set the setting matrix A at a series of checkpoints within a rotation
    scan. There would typically be n+1 points, where n is the number of images
    in the scan. The first point is the state at the beginning of the rotation
    scan. The final point is the state at the end of the rotation scan.
    Intervening points give the state at the start of the rotation at the 2nd
    to the nth image.

    This data is held separately from the 'static' U and B because per-image
    setting matrices may be refined whilst restraining to a previously
    determined best-fit static UB. The values will be reset if any changes are
    made to the static U and B matrices.
    N(   R   R   t   _A_at_scan_pointst   lenR    (   R   t   A_listt   e(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   set_A_at_scan_points¬   s    %c         C   s   |  j  | S(   sp  Return the setting matrix with index t.

    This will typically have been
    set with reference to a particular scan, such that it equals the UB matrix
    appropriate at the start of the rotation for the image with array index t

    :param t: index into the list of scan points.

    :returns: The A matrix at index t
    :rtype: :py:class:`scitbx.matrix.sqr`
    (   RT   (   R   RM   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR2   ½   s    c         C   s*   |  j  | ƒ } |  j | } | | j ƒ  S(   sµ   
    Return orientation matrix with index t.

    :param t: index into the list of scan points.

    :returns: The U matrix at index t
    :rtype: :py:class:`scitbx.matrix.sqr`
    (   R3   RT   R   (   R   RM   t   Btt   At(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR4   Ì   s    
c         C   sA   |  j  | } t d | j ƒ  j ƒ  ƒ } t j | j ƒ  ƒ j ƒ  S(   s»   
    Return orthogonalisation matrix with index t.

    :param t: index into the list of scan points.

    :returns: The B matrix at index t
    :rtype: :py:class:`scitbx.matrix.sqr`
    t   orthogonalization_matrix(   RT   R   RP   R   R   R   RO   (   R   RM   RZ   R9   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR3   Û   s    
c         C   s,   |  j  | } t d | j ƒ  j ƒ  ƒ } | S(   sÂ   
    Return unit cell with index t.

    :param t: index into the list of scan points.
    :type t: int

    :returns: The unit cell at index t
    :rtype: :py:class:`cctbx.uctbx.unit_cell`
    R[   (   RT   R   RP   R   (   R   RM   RZ   R9   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR5   ê   s    c         C   s   d |  _  d  |  _ d  S(   Ni    (   R    R	   RT   (   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR   ú   s    	c         C   s   |  j  S(   sO   
    :returns: The unit cell
    :rtype: :py:class:`cctbx.uctbx.unit_cell`
    (   RK   (   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR&   þ   s    c         C   s   | |  _  d S(   sL   
    :param space_group:
    :type space_group: cctbx.sgtbx.space_group
    N(   R   (   R   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   set_space_group  s    c         C   s   |  j  S(   s[   
    :returns: The current space group
    :rtype: :py:class:`cctbx.sgtbx.space_group`
    (   R   (   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR)     s    c         C   s2   d d l  m } | t k r+ |  j d | S|  j S(   sì   
    Get the current value of the mosaicity.

    :param deg: If True, return the mosaicity in degrees, else return the
                mosaicity in radians.
    :type deg: bool
    :returns: The mosaicity
    :rtype: float or None
    iÿÿÿÿ(   t   pig     €f@(   t   mathR]   R-   R   (   R   R   R]   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   get_mosaicity  s    
c         C   s=   d d l  m } | t k r0 | | d |  _ n	 | |  _ d S(   s-  
    Update the value of the mosaicity.

    :param mosaicity: The mosaicity
    :type mosaicity: float
    :param deg: If True, assume the mosaicity is given in degrees, else
                assume it is given in radians.
    :type deg: bool
    :returns: The mosaicity
    :rtype: float or None
    iÿÿÿÿ(   R]   g     €f@N(   R^   R]   R-   R   (   R   R   R   R]   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR   #  s    c         C   s   |  j  |  j S(   N(   R   R   (   R   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   get_A5  s    gH¯¼šò×z>c         C   s‚  t  | t ƒ r~t |  j | j ƒ } t g  t |  j | j ƒ D] \ } } t | | ƒ ^ q> ƒ } t g  t |  j | j ƒ D] \ } } t | | ƒ ^ q| ƒ }	 |  j d k rJ| j |  j k rÆ t	 Sx� t
 |  j ƒ D]m }
 |  j |
 ƒ | j |
 ƒ } } t g  t | | ƒ D] \ } } t | | ƒ ^ qƒ } | | k rÖ t	 SqÖ Wn  | | k o}| | k o}|	 | k o}|  j | j k St S(   Ni    (   t
   isinstanceR   t   absR   t   sumt   zipR   R   R!   t   FalseR1   R2   R   t   NotImplemented(   R   t   othert   epst   d_mosaicityt   u1t   u2t   d_Ut   b1t   b2t   d_BR?   t   A1t   A2t   a1t   a2t   d_A(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   __eq__8  s"    >> 8 g{®Gáz„?gš™™™™™é?g      ð?c         C   s‰  |  j  ƒ  | j  ƒ  k r t S|  j d t ƒ | j d t ƒ } } t | | ƒ t | | ƒ } }	 | d k r |	 d k r“ t Sn | |	 | k  r“ t S|  j ƒ  | j ƒ  }
 } |
 j ƒ  s¾ t ‚ | j ƒ  sÐ t ‚ | |
 j	 ƒ  } | j
 ƒ  } | j d t ƒ d } t | ƒ | k rt S|  j ƒ  | j ƒ  } } | j | d | d | ƒsPt S|  j d k r…| j |  j k rut Sxt |  j ƒ D]ù } |  j | ƒ | j | ƒ }
 } |
 j ƒ  s¼t ‚ | j ƒ  sÎt ‚ | |
 j	 ƒ  } | j
 ƒ  } | j d t ƒ d } t | ƒ | k rt S|  j | ƒ | j | ƒ } } t | t ƒ j ƒ  } t | t ƒ j ƒ  } | j | d | d | ƒs…t Sq…Wn  t S(   s,  
    Test similarity of this to another crystal model

    :param other: the crystal model to test against
    :type other: crystal_model
    :param angle_tolerance: maximum tolerated orientation difference in degrees
    :type angle_tolerance: float
    :param mosaicity_tolerance: minimum tolerated fraction of the larger
            mosaicity for the smaller mosaicity to retain similarity
    :type mosaicity_tolerance:float
    :param uc_rel_length_tolerance: relative length tolerance to pass to
            unit_cell.is_similar_to
    :type uc_rel_length_tolerance: float
    :param uc_abs_angle_tolerance: absolute angle tolerance to pass to
            unit_cell.is_similar_to
    :type uc_abs_angle_tolerance: float
    :returns: Whether the other crystal model is similar to this
    :rtype: bool
    R   g        i    t   relative_length_tolerancet   absolute_angle_tolerance(   R)   Re   R_   R-   t   mint   maxR+   RQ   R
   RP   t%   r3_rotation_matrix_as_unit_quaterniont!   unit_quaternion_as_axis_and_angleRb   R&   t   is_similar_toR!   R1   R4   R3   R   R   (   R   Rg   t   angle_tolerancet   mosaicity_tolerancet   uc_rel_length_tolerancet   uc_abs_angle_tolerancet   m_at   m_bt   min_mt   max_mt   U_at   U_bt   R_abt   uqRJ   t   uc_at   uc_bR?   t   B_at   B_b(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR|   I  sT     %   	   	 c         C   sL   |  j  ƒ  j ƒ  } t j | d  ƒ t j | d d !ƒ t j | d d !ƒ f S(   s™   
    Get the real space unit cell basis vectors.

    :returns: Real space unit cell basis vectors
    :rtype: list of :py:class:`scitbx.matrix.col`
    i   i   i	   (   R`   R   R   R   (   R   t   A_inv(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   get_real_space_vectorsŽ  s    c         C   sû   |  j  ƒ  j ƒ  } t j | j ƒ  j ƒ  j ƒ  j ƒ  ƒ } | | } | d  } | d d !} | d d !} t | | | d |  j	 ƒ  j
 | ƒ d |  j ƒ  ƒ} |  j d k r÷ | j ƒ  }	 | j g  |  j D] }
 |
 |	 ^ qÅ ƒ | j |  j k s÷ t ‚ n  | S(   sI  
    Returns a copy of the current crystal model transformed by the given
    change of basis operator to the new basis.

    :param change_of_basis_op: The change of basis operator.
    :type cctbx.sgtbx.change_of_basis_op:
    :returns: The crystal model transformed to the new basis.
    :rtype: :py:class:`crystal_model`
    i   i   i	   R   R   i    (   R`   R   R   R   t   c_invt   rRP   t	   as_doubleR   R)   t   change_basisR_   R!   RX   RT   R
   (   R   t   change_of_basis_opt   direct_matrixt   Mt   new_direct_matrixR   R   R   Rg   t   M_invRZ   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR’   š  s$    '

	!c         C   sX   | j  |  _  | j |  _ | j |  _ | j |  _ | j |  _ | j |  _ | j |  _ d S(   sš   
    Update the current crystal model such that self == other.

    :param other: A crystal model to update self with.
    :type other: crystal_model
    N(   R   R   RT   R    R   RK   R   (   R   Rg   (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   updateÍ  s    N("   t   __name__t
   __module__t   __doc__R	   R-   R   t   propertyR!   Re   RB   RH   R   R5   R   RR   R+   R/   RS   RX   R2   R4   R3   R   R&   R\   R)   R_   R   R`   Ru   R|   RŽ   R’   R˜   (    (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyR      s@   $5		
							
										C		3c      
   C   s  | s t  d ƒ } n  t j |  ƒ } | j ƒ  } | r| | j ƒ  } t j | j d d !ƒ } | d | j ƒ  } | | 9} n | r� | | 9} n  | j d d !} | j d d !} | j d d !}	 t j d	 ƒ }
 |
 | } |
 | } |
 |	 } t | | | d | ƒS(
   s  
  Create a crystal_model from a Mosflm A matrix (a*, b*, c*); N.B. assumes
  the mosflm coordinate frame::

                                                   /!
                      Y-axis                      / !
                        ^                        /  !
                        !                       /   !
                        !                      /    !
                        !   /                 /  Xd !
                        !  /                 / * ^  !
                        ! /                  ! 3 !  !
                        !/      X-ray beam   !   !  !
                        /------------------------/--!---->X-axis
                       /                     !  / *1!
                    <-/-                     ! /    !
                     /  \+ve phi             ! Yd  /
                    /   /                    ! 2  /
                   /                         ! * /
                  Z-axis                  Ys ^ _/
                Rotation                     ! /| Xs
                 axis                        !/
                                             O

  Also assume that the mosaic spread is 0.

  :param mosflm_A_matrix: The A matrix in Mosflm convention.
  :type mosflm_A_matrix: tuple of floats
  :param unit_cell: The unit cell parameters which are used to determine the
                    wavelength from the Mosflm A matrix.
  :type unit_cell: cctbx.uctbx.unit_cell
  :param wavelength: The wavelength to scale the A matrix
  :type wavelength: float
  :param space_group: If the space group is None then the space_group will
                      be assigned as P1
  :type space_group: cctbx.sgtbx.space_group
  :returns: A crystal model derived from the given Mosflm A matrix
  :rtype: :py:class:`crystal_model`
  t   P1i    i   i   i	   i   iÿÿÿÿR   (	   i    i    i   i    i   i    iÿÿÿÿi    i    (	   R   R   R   R   R'   R   R   RI   R   (   t   mosflm_A_matrixR   t
   wavelengthR   t   A_starR   t   unit_cell_constantst   at   bt   ct   rotate_mosflm_to_imgCIFt   _at   _bt   _c(    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt    crystal_model_from_mosflm_matrixÜ  s&    ,


N(   t
   __future__R    t   scitbxR   t   cctbx.uctbxR   t   cctbx.sgtbxR   R   R   t   cctbx.crystal_orientationR   t   objectR   R	   R©   (    (    (    sA   /public2/ftp/pub/ccp4/6.5/ccp4-6.5/lib/py2/dxtbx/model/crystal.pyt   <module>   s   ÿ Ö