Exemplo n.º 1
0
 def __init__(self, wavelength=None, energy=None, energy_eV=None, frequency=None):
     if (
         (wavelength is not None and energy is not None)
         or (wavelength is not None and energy_eV is not None)
         or (energy is not None and energy_eV is not None)
     ):
         log_and_raise_error(
             logger,
             "Invalid arguments during initialisation of Photon instance. More than one of the arguments is not None.",
         )
         return
     if wavelength is not None:
         self.set_wavelength(wavelength)
     elif energy is not None:
         self.set_energy(energy)
     elif energy_eV is not None:
         self.set_energy_eV(energy_eV)
     elif frequency is not None:
         self.set_frequency(frequency)
     else:
         log_and_raise_error(
             logger,
             "Photon could not be initialised."
             "It has to be initialized with exactly one of the following keyword arguments"
             "\t- wavelegth:\t photon wavelength in meters"
             "\t- energy:\t photon energy in Joules"
             "\t- energy_eV:\t photon energy in electron volts"
             "\t- frequency:\t photon frequency in Hertz",
         )
Exemplo n.º 2
0
    def set_model(self, model):
        """
        Set the model

        Args:
    
          :model (str): Model for the spatial illumination profile
        
            *Choose one of the following options:*

              - ``None`` - flat illumination profile of infinite extent and the intensity at every point corresponds to the intensity of a top hat profile (see below)

              - ``\'top_hat\'`` - Circular top hat profile
    
              - ``\'pseudo_lorentzian\'`` - 2D radially symmetrical profile composed of two Gaussian profiles obtained by a fit to a Lorentzian profile (used instead of a real Lorentzian because this function can be normalised)

              - ``\'gaussian\'`` - 2D radially symmetrical Gaussian profile
        """
        if model is None or model in [
                "top_hat", "pseudo_lorentzian", "gaussian"
        ]:
            self._model = model
        else:
            log_and_raise_error(
                logger,
                "Pulse profile model %s is not implemented. Change your configuration and try again."
                % model)
            sys.exit(0)
Exemplo n.º 3
0
 def __init__(self, values=None, formalism=None):
     """
    """
     if values is None and formalism is None:
         single = True
     elif formalism.startswith("euler_angles_") and len(formalism) == len("euler_angles_xyz"):
         values = numpy.asarray(values)
         single = values.ndim == 1
     elif formalism == "rotation_matrix":
         values = numpy.asarray(values)
         single = values.ndim == 2 
     elif formalism == "quaternion":
         values = numpy.asarray(values)
         single = values.ndim == 1
     elif formalism in ["random","random_x","random_y","random_z"]:
         single = True
     else:
         log_and_raise_error(logger, "formalism=%s is not implemented" % formalism)
         return
     self._formalism = formalism
     self._i = 0
     self._values = values
     # Initialise rotations
     if single:
         if values is None:
             # No rotation (rotation matrix = identity matrix)
             self._rotations = [Rotation()]
         else:
             self._rotations = [Rotation(values, formalism=formalism)]
     else:
         self._rotations = []
         for i in range(len(values)):
             self._rotations.append(Rotation(values[i], formalism=formalism))
Exemplo n.º 4
0
    def rotate_vector(self, vector, order="xyz"):
        r"""
        Return the rotated copy of a given vector

        Args:
           :vector (array): 3D vector

        Kwargs:
           :order (str): Order of geometrical axes in array representation of the given vector (default ``'xyz'``)
        """
        # Check input
        if vector.size != 3 or vector.ndim != 1:
            log_and_raise_error(
                logger,
                "Cannot rotate vector. Vector has incompatible size (%i) or number of dimensions (%i)."
                % (vector.size, vector.ndim))
            return
        # Rotate
        if order == "xyz":
            return self.rotation_matrix.dot(vector)
        elif order == "zyx":
            return self.rotation_matrix.dot(vector[::-1])
        else:
            log_and_raise_error(logger,
                                "Corrdinates in order=%s is invalid." % order)
Exemplo n.º 5
0
    def set_mode(self, mode):
        r"""
        Set the mode of variation

        Args:
          :mode (str): Mode of variation

            *Choose one of the following options*
           
            ======================= ==================================================================== =====================================================
            ``mode``                Variation model                                                      ``spread`` parameter
            ======================= ==================================================================== =====================================================
            ``None``                No variation                                                         -
            ``'uniform'``           Uniform random distribution                                          Width
            ``'normal'``            Normal random distribution                                           Standard deviation
            ``'poisson'``           Poissonian random distribution                                       -
            ``'normal_poisson'``    Normal on top of Poissonian random dist.                             Std. dev. of normal distribution
            ``'range'``             Equispaced grid around mean center position                          Width
            ======================= ==================================================================== =====================================================
        """
        if mode not in [
                None, "normal", "poisson", "normal_poisson", "uniform", "range"
        ]:
            log_and_raise_error(
                logger,
                "Variation object cannot be configured with illegal mode %s" %
                mode)
            return
        self._mode = mode
Exemplo n.º 6
0
def generate_qmap_3d(qn, qmax, extrinsic_rotation=None, order='xyz'):
    q = numpy.linspace(-qmax, qmax, qn)
    Qz, Qy, Qx = numpy.meshgrid(q, q, q, indexing='ij')
    qmap = numpy.zeros(shape=(qn, qn, qn, 3), dtype='float')
    if order == 'xyz':
        qmap[:, :, :, 0] = Qx[:, :, :]
        qmap[:, :, :, 1] = Qy[:, :, :]
        qmap[:, :, :, 2] = Qz[:, :, :]
    elif order == 'zyx':
        qmap[:, :, :, 2] = Qx[:, :, :]
        qmap[:, :, :, 1] = Qy[:, :, :]
        qmap[:, :, :, 0] = Qz[:, :, :]
    else:
        log_and_raise_error(
            logger,
            "order=\'%s\' is not a recognised argument for this function." %
            str(order))
        return
    if extrinsic_rotation is not None:
        log_debug(logger, "Applying qmap rotation.")
        intrinsic_rotation = copy.deepcopy(extrinsic_rotation)
        intrinsic_rotation.invert()
        qmap = intrinsic_rotation.rotate_vectors(
            qmap.ravel(), order=order).reshape(qmap.shape)
    return qmap
Exemplo n.º 7
0
 def __init__(self,
              wavelength=None,
              energy=None,
              energy_eV=None,
              frequency=None):
     if (wavelength is not None and energy is not None) or (
             wavelength is not None
             and energy_eV is not None) or (energy is not None
                                            and energy_eV is not None):
         log_and_raise_error(
             logger,
             "Invalid arguments during initialisation of Photon instance. More than one of the arguments is not None."
         )
         return
     if wavelength is not None:
         self.set_wavelength(wavelength)
     elif energy is not None:
         self.set_energy(energy)
     elif energy_eV is not None:
         self.set_energy_eV(energy_eV)
     elif frequency is not None:
         self.set_frequency(frequency)
     else:
         log_and_raise_error(
             logger, "Photon could not be initialised."
             "It has to be initialized with exactly one of the following keyword arguments"
             "\t- wavelegth:\t photon wavelength in meters"
             "\t- energy:\t photon energy in Joules"
             "\t- energy_eV:\t photon energy in electron volts"
             "\t- frequency:\t photon frequency in Hertz")
Exemplo n.º 8
0
 def set_number_of_dimensions(self, number_of_dimensions):
     if number_of_dimensions < 1 or number_of_dimensions > 3:
         log_and_raise_error(
             logger,
             "Number of dimensions for variation objects can be only either 1, 2 or 3."
         )
         return
     self._number_of_dimensions = number_of_dimensions
Exemplo n.º 9
0
def generate_qmap(X,
                  Y,
                  pixel_size,
                  detector_distance,
                  wavelength,
                  extrinsic_rotation=None,
                  order="xyz"):
    r"""
    Generate scattering vector map from experimental parameters

    Args:
      :X (array): :math:`x`-coordinates of pixels in unit meter

      :Y (array): :math:`y`-coordinates of pixels in unit meter

      :pixel_size (float): Pixel size (i.e. edge length) in unit meter

      :detector_distance (float): Distance from interaction point to detector plane

      :wavelength (float): Photon wavelength in unit meter

    Kwargs:
      :extrinsic_rotation (:class:`condor.utils.rotation.Rotation`): Extrinsic rotation of the sample. If ``None`` no rotation is applied (default ``None``)

      :order (str): Order of scattering vector coordinates in the output array. Choose either ``'xyz'`` or ``'zyx'`` (default ``'xyz'``)    
    """
    log_debug(logger,
              "Allocating qmap (%i,%i,%i)" % (X.shape[0], X.shape[1], 3))
    R_Ewald = 2 * numpy.pi / wavelength
    p_x = X * pixel_size
    p_y = Y * pixel_size
    p_z = numpy.ones_like(X) * detector_distance
    l = numpy.sqrt(p_x**2 + p_y**2 + p_z**2)
    r_x = p_x / l
    r_y = p_y / l
    r_z = p_z / l - 1.
    qmap = numpy.zeros(shape=(X.shape[0], X.shape[1], 3))
    if order == "xyz":
        qmap[:, :, 0] = r_x * R_Ewald
        qmap[:, :, 1] = r_y * R_Ewald
        qmap[:, :, 2] = r_z * R_Ewald
    elif order == "zyx":
        qmap[:, :, 0] = r_z * R_Ewald
        qmap[:, :, 1] = r_y * R_Ewald
        qmap[:, :, 2] = r_x * R_Ewald
    else:
        log_and_raise_error(logger,
                            "Indexing with order=%s is invalid." % order)
    if extrinsic_rotation is not None:
        log_debug(logger, "Applying qmap rotation.")
        intrinsic_rotation = copy.deepcopy(extrinsic_rotation)
        intrinsic_rotation.invert()
        qmap = intrinsic_rotation.rotate_vectors(
            qmap.ravel(), order=order).reshape(qmap.shape)
    return qmap
Exemplo n.º 10
0
    def rotate_vectors(self, vectors, order="xyz"):
        r"""
        Return the rotated copy of a given array of vectors

        Args:
           :vectors (array): Array of 3D vectors with shape (:math:`N`, 3) with :math:`N` denoting the number of 3D vectors

        Kwargs:
           :order (str): Order of geometrical axes in array representation of the given vector (default ``'xyz'``)
        """        
        # Check input
        if vectors.ndim != 2 and vectors.ndim != 1:
            log_and_raise_error(logger, "Cannot rotate vectors. Input must have either one or two dimensions")
            return           
        n_ax = list(vectors.shape)[-1]
        N = vectors.size
        Nv = N/3
        if vectors.ndim == 2 and n_ax != 3:
            log_and_raise_error(logger, "Cannot rotate vectors. The given array has length %i in last dimension but should be 3." % (n_ax))
            return
        if vectors.ndim == 1 and N % 3 != 0:
            log_and_raise_error(logger, "Cannot rotate vectors. The given array has size %i which is not a multiple of 3." % (n_ax))
            return
        # Rotate
        if order == "xyz":
            return numpy.array([numpy.dot(self.rotation_matrix,vectors.ravel()[i*3:(i+1)*3]) for i in numpy.arange(Nv)])
        elif order == "zyx":
            return numpy.array([numpy.dot(self.rotation_matrix,(vectors.ravel()[i*3:(i+1)*3])[::-1])[::-1] for i in numpy.arange(Nv)])
        else:
            log_and_raise_error(logger, "Corrdinates in order=%s is invalid." % order)
Exemplo n.º 11
0
    def set_with_euler_angles(self, euler_angles, rotation_axes="zxz"):
        r"""
        Set rotation with an array of three euler angles

        Args:
           :euler_angles: Array of the three euler angles representing consecutive rotations

        Kwargs:
           :rotation_axes(str): Rotation axes of the three consecutive rotations (default = \'zxz\') 
        """
        # Check input
        if euler_angles.size != 3:
            log_and_raise_error(logger, "Size of rotation variable does not match expected shape")
            return
        # Set rotation matrix
        self.rotation_matrix = euler_to_rotmx(euler_angles, rotation_axes)
Exemplo n.º 12
0
def get_values_window(image,
                      x_i,
                      y_i,
                      window_size,
                      circle_window,
                      i,
                      masked_image=None,
                      thumbnails=None):

    if not window_size % 2:
        log_and_raise_error(
            logger,
            "window_size (%i) must be an odd number. Please change your configuration and try again."
            % window_size)
        return None

    if (x_i-window_size/2 < 0) or \
       x_i-window_size/2+window_size>=image.shape[1] or \
       (y_i-window_size/2 < 0) or \
       y_i-window_size/2+window_size>=image.shape[0]:
        log_info(logger, "Particle too close to edge - cannot be analysed.")
        return None

    values = image[y_i - (window_size - 1) / 2:y_i + (window_size - 1) / 2 + 1,
                   x_i - (window_size - 1) / 2:x_i + (window_size - 1) / 2 + 1]

    if circle_window:
        mask = make_circle_mask(window_size)
        values = values[mask]

        if masked_image is not None:
            (masked_image[y_i - (window_size - 1) / 2:y_i +
                          (window_size - 1) / 2 + 1,
                          x_i - (window_size - 1) / 2:x_i +
                          (window_size - 1) / 2 + 1])[mask] = values[:]
        if thumbnails is not None:
            (thumbnails[i, :, :])[mask] = values[:]
    else:
        if masked_image is not None:
            masked_image[y_i - (window_size - 1) / 2:y_i +
                         (window_size - 1) / 2 + 1,
                         x_i - (window_size - 1) / 2:x_i +
                         (window_size - 1) / 2 + 1] = values[:, :]
        if thumbnail is not None:
            thumbnails[i, :, :] = values[:, :]

    return values
Exemplo n.º 13
0
def generate_qmap(X,Y,pixel_size,detector_distance,wavelength,extrinsic_rotation=None, order="xyz"):
    r"""
    Generate scattering vector map from experimental parameters

    Args:
      :X (array): :math:`x`-coordinates of pixels in unit meter

      :Y (array): :math:`y`-coordinates of pixels in unit meter

      :pixel_size (float): Pixel size (i.e. edge length) in unit meter

      :detector_distance (float): Distance from interaction point to detector plane

      :wavelength (float): Photon wavelength in unit meter

    Kwargs:
      :extrinsic_rotation (:class:`condor.utils.rotation.Rotation`): Extrinsic rotation of the sample. If ``None`` no rotation is applied (default ``None``)

      :order (str): Order of scattering vector coordinates in the output array. Choose either ``'xyz'`` or ``'zyx'`` (default ``'xyz'``)    
    """
    log_debug(logger, "Allocating qmap (%i,%i,%i)" % (X.shape[0],X.shape[1],3))
    R_Ewald = 2*numpy.pi/wavelength
    p_x = X*pixel_size
    p_y = Y*pixel_size
    p_z = numpy.ones_like(X)*detector_distance
    l = numpy.sqrt(p_x**2+p_y**2+p_z**2)
    r_x = p_x/l
    r_y = p_y/l
    r_z = p_z/l - 1.
    qmap = numpy.zeros(shape=(X.shape[0],X.shape[1],3))
    if order == "xyz":
        qmap[:,:,0] = r_x * R_Ewald
        qmap[:,:,1] = r_y * R_Ewald
        qmap[:,:,2] = r_z * R_Ewald
    elif order == "zyx":
        qmap[:,:,0] = r_z * R_Ewald
        qmap[:,:,1] = r_y * R_Ewald
        qmap[:,:,2] = r_x * R_Ewald
    else:
        log_and_raise_error(logger, "Indexing with order=%s is invalid." % order)
    if extrinsic_rotation is not None:
        log_debug(logger, "Applying qmap rotation.")
        intrinsic_rotation = copy.deepcopy(extrinsic_rotation)
        intrinsic_rotation.invert()
        qmap = intrinsic_rotation.rotate_vectors(qmap.ravel(), order=order).reshape(qmap.shape)
    return qmap
Exemplo n.º 14
0
    def set_with_quaternion(self, quaternion):
        r"""
        Set rotation with a quaternion

        Args:
           :quaternion: Numpy array representing the quaternion :math:`w+ix+jy+kz`: 

                        [:math:`w`, :math:`x`, :math:`y`, :math:`z`] = [:math:`\cos(\theta/2)`, :math:`u_x \sin(\theta/2)`, :math:`u_y \sin(\theta/2)`, :math:`u_z \sin(\theta/2)`] 

                        with :math:`\theta` being the rotation angle and :math:`\vec{u}=(u_x,u_y,u_z)` the unit vector that defines the axis of rotation.
        """
        # Check input
        if quaternion.size != 4:
            log_and_raise_error(logger, "Size of rotation variable does not match expected shape")
            return
        # Set rotation matrix
        self.rotation_matrix = rotmx_from_quat(quaternion)
Exemplo n.º 15
0
    def set_with_rotation_matrix(self, rotation_matrix):
        r"""
        Set rotation with a rotation matrix

        Args:
           :rotation_matrix: 3x3 array representing the rotation matrix
        """
        # Check input
        if rotation_matrix.size != 9 or rotation_matrix.ndim != 2:
            log_and_raise_error(logger, "Size of rotation variable does not match expected shape")
            return
        I = rotation_matrix.dot(rotation_matrix.T)
        tol = 0.0001
        for i in range(3):
            if abs(I[i,i]-1.) > tol:
                log_and_raise_error(logger, "Given matrix cannot be a rotation matrix because it is not unitary")
        # Set rotation matrix
        self.rotation_matrix = rotation_matrix.copy()
Exemplo n.º 16
0
    def set_with_euler_angles(self, euler_angles, rotation_axes="zxz"):
        r"""
        Set rotation with an array of three euler angles

        Args:
           :euler_angles: Array of the three euler angles representing consecutive rotations

        Kwargs:
           :rotation_axes(str): Rotation axes of the three consecutive rotations (default = \'zxz\') 
        """
        # Check input
        if euler_angles.size != 3:
            log_and_raise_error(
                logger,
                "Size of rotation variable does not match expected shape")
            return
        # Set rotation matrix
        self.rotation_matrix = euler_to_rotmx(euler_angles, rotation_axes)
Exemplo n.º 17
0
    def __init__(self, values=None, formalism=None):
        self.rotation_matrix = None
        if values is None and formalism is None:
            # No rotation (rotation matrix = identity matrix)
            self.rotation_matrix = numpy.ones(shape=(3,3))
        elif formalism.startswith("euler_angles_") and len(formalism) == len("euler_angles_xyz"):
            self.set_with_euler_angles(values, rotation_axes=formalism[-3:])
        elif formalism == "rotation_matrix":
            self.set_with_rotation_matrix(values)
        elif formalism == "quaternion":
            self.set_with_quaternion(values)
        elif formalism in ["random","random_x","random_y","random_z"]:
            if values is not None:
                log_warning(logger, "Specified formalism=%s but values is not None." % formalism)

            self._set_as_random_formalism(formalism)
        else:
            log_and_raise_error(logger, "formalism=%s is not implemented" % formalism)
            return
Exemplo n.º 18
0
    def set_with_quaternion(self, quaternion):
        r"""
        Set rotation with a quaternion

        Args:
           :quaternion: Numpy array representing the quaternion :math:`w+ix+jy+kz`: 

                        [:math:`w`, :math:`x`, :math:`y`, :math:`z`] = [:math:`\cos(\theta/2)`, :math:`u_x \sin(\theta/2)`, :math:`u_y \sin(\theta/2)`, :math:`u_z \sin(\theta/2)`] 

                        with :math:`\theta` being the rotation angle and :math:`\vec{u}=(u_x,u_y,u_z)` the unit vector that defines the axis of rotation.
        """
        # Check input
        if quaternion.size != 4:
            log_and_raise_error(
                logger,
                "Size of rotation variable does not match expected shape")
            return
        # Set rotation matrix
        self.rotation_matrix = rotmx_from_quat(quaternion)
Exemplo n.º 19
0
    def rotate_vector(self, vector, order="xyz"):
        r"""
        Return the rotated copy of a given vector

        Args:
           :vector (array): 3D vector

        Kwargs:
           :order (str): Order of geometrical axes in array representation of the given vector (default ``'xyz'``)
        """
        # Check input
        if vector.size != 3 or vector.ndim != 1:
            log_and_raise_error(logger, "Cannot rotate vector. Vector has incompatible size (%i) or number of dimensions (%i)." % (vector.size,vector.ndim))
            return
        # Rotate
        if order == "xyz":
            return self.rotation_matrix.dot(vector)
        elif order == "zyx":
            return self.rotation_matrix.dot(vector[::-1])
        else:
            log_and_raise_error(logger, "Corrdinates in order=%s is invalid." % order)
Exemplo n.º 20
0
def euler_to_rotmx(euler_angles, rotation_axes="zxz"):
    r"""
    Obtain rotation matrix from three euler angles and the rotation axes

    Args:
      :euler_angles (array): Length-3 array of euler angles

    Kwargs:
      :rotation_axes (str): Rotation axes of the three consecutive Euler rotations (default ``'zxz'``) 
    """
    R = numpy.identity(3)
    for ang,ax in zip(euler_angles, rotation_axes):
        if ax == "x":
            R = R.dot(R_x(ang))
        elif ax == "y":
            R = R.dot(R_y(ang))
        elif ax == "z":
            R = R.dot(R_z(ang))
        else:
            log_and_raise_error(logger, "%s is not a valid axis" % ax)
            return
    return R
Exemplo n.º 21
0
def euler_to_rotmx(euler_angles, rotation_axes="zxz"):
    r"""
    Obtain rotation matrix from three euler angles and the rotation axes

    Args:
      :euler_angles (array): Length-3 array of euler angles

    Kwargs:
      :rotation_axes (str): Rotation axes of the three consecutive Euler rotations (default ``'zxz'``) 
    """
    R = numpy.identity(3)
    for ang, ax in zip(euler_angles, rotation_axes):
        if ax == "x":
            R = R.dot(R_x(ang))
        elif ax == "y":
            R = R.dot(R_y(ang))
        elif ax == "z":
            R = R.dot(R_z(ang))
        else:
            log_and_raise_error(logger, "%s is not a valid axis" % ax)
            return
    return R
Exemplo n.º 22
0
    def rotate_vectors(self, vectors, order="xyz"):
        r"""
        Return the rotated copy of a given array of vectors

        Args:
           :vectors (array): Array of 3D vectors with shape (:math:`N`, 3) with :math:`N` denoting the number of 3D vectors

        Kwargs:
           :order (str): Order of geometrical axes in array representation of the given vector (default ``'xyz'``)
        """
        # Check input
        if vectors.ndim != 2 and vectors.ndim != 1:
            log_and_raise_error(
                logger,
                "Cannot rotate vectors. Input must have either one or two dimensions"
            )
            return
        n_ax = list(vectors.shape)[-1]
        N = vectors.size
        Nv = N / 3
        if vectors.ndim == 2 and n_ax != 3:
            log_and_raise_error(
                logger,
                "Cannot rotate vectors. The given array has length %i in last dimension but should be 3."
                % (n_ax))
            return
        if vectors.ndim == 1 and N % 3 != 0:
            log_and_raise_error(
                logger,
                "Cannot rotate vectors. The given array has size %i which is not a multiple of 3."
                % (n_ax))
            return
        # Rotate
        if order == "xyz":
            return numpy.array([
                numpy.dot(self.rotation_matrix,
                          vectors.ravel()[i * 3:(i + 1) * 3])
                for i in numpy.arange(Nv)
            ])
        elif order == "zyx":
            return numpy.array([
                numpy.dot(self.rotation_matrix,
                          (vectors.ravel()[i * 3:(i + 1) * 3])[::-1])[::-1]
                for i in numpy.arange(Nv)
            ])
        else:
            log_and_raise_error(logger,
                                "Corrdinates in order=%s is invalid." % order)
Exemplo n.º 23
0
    def __init__(self, values=None, formalism=None):
        self.rotation_matrix = None
        if values is None and formalism is None:
            # No rotation (rotation matrix = identity matrix)
            self.rotation_matrix = numpy.ones(shape=(3, 3))
        elif formalism.startswith("euler_angles_") and len(formalism) == len(
                "euler_angles_xyz"):
            self.set_with_euler_angles(values, rotation_axes=formalism[-3:])
        elif formalism == "rotation_matrix":
            self.set_with_rotation_matrix(values)
        elif formalism == "quaternion":
            self.set_with_quaternion(values)
        elif formalism in ["random", "random_x", "random_y", "random_z"]:
            if values is not None:
                log_warning(
                    logger, "Specified formalism=%s but values is not None." %
                    formalism)

            self._set_as_random_formalism(formalism)
        else:
            log_and_raise_error(logger,
                                "formalism=%s is not implemented" % formalism)
            return
Exemplo n.º 24
0
    def set_with_rotation_matrix(self, rotation_matrix):
        r"""
        Set rotation with a rotation matrix

        Args:
           :rotation_matrix: 3x3 array representing the rotation matrix
        """
        # Check input
        if rotation_matrix.size != 9 or rotation_matrix.ndim != 2:
            log_and_raise_error(
                logger,
                "Size of rotation variable does not match expected shape")
            return
        I = rotation_matrix.dot(rotation_matrix.T)
        tol = 0.0001
        for i in range(3):
            if abs(I[i, i] - 1.) > tol:
                log_and_raise_error(
                    logger,
                    "Given matrix cannot be a rotation matrix because it is not unitary"
                )
        # Set rotation matrix
        self.rotation_matrix = rotation_matrix.copy()
Exemplo n.º 25
0
    def set_model(self,model):
        """
        Set the model

        Args:
    
          :model (str): Model for the spatial illumination profile
        
            *Choose one of the following options:*

              - ``None`` - flat illuminatrion profile of infinite extent and the intensity at every point corresponds to the intensity of a top hat profile (see below)

              - ``\'top_hat\'`` - Circular top hat profile
    
              - ``\'pseudo_lorentzian\'`` - 2D radially symmetrical profile composed of two Gaussian profiles obtained by a fit to a Lorentzian profile (used instead of a real Lorentzian because this function can be normalised)

              - ``\'gaussian\'`` - 2D radially symmetrical Gaussian profile
        """
        if model is None or model in ["top_hat","pseudo_lorentzian","gaussian"]:
            self._model = model
        else:
            log_and_raise_error(logger, "Pulse profile model %s is not implemented. Change your configuration and try again." % model)
            sys.exit(0)
Exemplo n.º 26
0
    def set_mode(self,mode):
        r"""
        Set the mode of variation

        Args:
          :mode (str): Mode of variation

            *Choose one of the following options*
           
            ======================= ==================================================================== =====================================================
            ``mode``                Variation model                                                      ``spread`` parameter
            ======================= ==================================================================== =====================================================
            ``None``                No variation                                                         -
            ``'uniform'``           Uniform random distribution                                          Width
            ``'normal'``            Normal random distribution                                           Standard deviation
            ``'poisson'``           Poissonian random distribution                                       -
            ``'normal_poisson'``    Normal on top of Poissonian random dist.                             Std. dev. of normal distribution
            ``'range'``             Equispaced grid around mean center position                          Width
            ======================= ==================================================================== =====================================================
        """
        if mode not in [None,"normal","poisson","normal_poisson","uniform","range"]:
            log_and_raise_error(logger, "Variation object cannot be configured with illegal mode %s" % mode)
            return
        self._mode = mode
Exemplo n.º 27
0
 def __init__(self, values=None, formalism=None):
     """
    """
     if values is None and formalism is None:
         single = True
     elif formalism.startswith("euler_angles_") and len(formalism) == len(
             "euler_angles_xyz"):
         values = numpy.asarray(values)
         single = values.ndim == 1
     elif formalism == "rotation_matrix":
         values = numpy.asarray(values)
         single = values.ndim == 2
     elif formalism == "quaternion":
         values = numpy.asarray(values)
         single = values.ndim == 1
     elif formalism in ["random", "random_x", "random_y", "random_z"]:
         single = True
     else:
         log_and_raise_error(logger,
                             "formalism=%s is not implemented" % formalism)
         return
     self._formalism = formalism
     self._i = 0
     self._values = values
     # Initialise rotations
     if single:
         if values is None:
             # No rotation (rotation matrix = identity matrix)
             self._rotations = [Rotation()]
         else:
             self._rotations = [Rotation(values, formalism=formalism)]
     else:
         self._rotations = []
         for i in range(len(values)):
             self._rotations.append(Rotation(values[i],
                                             formalism=formalism))
Exemplo n.º 28
0
 def validate(self):
     mode = self.get_mode()
     spread = self.get_spread()
     number_of_dimensions = self.get_number_of_dimensions()
     if mode in ["normal","normal_poisson","uniform","range"] and spread is None:
         log_and_raise_error(logger, "Variation object configuration is invalid because mode \'%s\' requires \'spread\' to be not None." % mode)
     if mode in ["range"]:
         if self.n is None:
             log_and_raise_error(logger, "Variation object cannot be configured because mode \'%s\' requires that \'n\' is not None." % mode)
     if spread is not None:
         if number_of_dimensions != len(self._spread):
             log_and_raise_error(logger, "Specified number of dimensions (%i) and length of spread array (%i) do not match." % (number_of_dimensions, len(spread)))
Exemplo n.º 29
0
 def validate(self):
     mode = self.get_mode()
     spread = self.get_spread()
     number_of_dimensions = self.get_number_of_dimensions()
     if mode in ["normal", "normal_poisson", "uniform", "range"
                 ] and spread is None:
         log_and_raise_error(
             logger,
             "Variation object configuration is invalid because mode \'%s\' requires \'spread\' to be not None."
             % mode)
     if mode in ["range"]:
         if self.n is None:
             log_and_raise_error(
                 logger,
                 "Variation object cannot be configured because mode \'%s\' requires that \'n\' is not None."
                 % mode)
     if spread is not None:
         if number_of_dimensions != len(self._spread):
             log_and_raise_error(
                 logger,
                 "Specified number of dimensions (%i) and length of spread array (%i) do not match."
                 % (number_of_dimensions, len(spread)))
Exemplo n.º 30
0
 def set_number_of_dimensions(self, number_of_dimensions):
     if number_of_dimensions < 1 or number_of_dimensions > 3:
         log_and_raise_error(logger, "Number of dimensions for variation objects can be only either 1, 2 or 3.")
         return
     self._number_of_dimensions = number_of_dimensions
Exemplo n.º 31
0
def read_map(filename):
    log.log_info(logger, "Automatic scaling of EM maps may not be reliable. Please make sure to check your map after using this functionality.")
    # CCP4 map file format
    # http://www.ccp4.ac.uk/html/maplib.html
    with open(filename, "rb") as f:
        # 1024 bytes header
        header_buf = f.read(1024)
        temp_int32 = numpy.frombuffer(header_buf, dtype="int32")
        temp_float32 = numpy.frombuffer(header_buf, dtype="float32")
        #1      NC              # of Columns    (fastest changing in map)
        #2      NR              # of Rows
        #3      NS              # of Sections   (slowest changing in map)
        NC = temp_int32[0]
        NR = temp_int32[1]
        NS = temp_int32[2]
        if NC != NR or NR != NS:
            log.log_and_raise_error(logger, "Cannot read a map with unequal dimensions")
        N = NC
        #4      MODE            Data type
        #                  0 = envelope stored as signed bytes (from
        #                      -128 lowest to 127 highest)
        #                  1 = Image     stored as Integer*2
        #                  2 = Image     stored as Reals
        #                  3 = Transform stored as Complex Integer*2
        #                  4 = Transform stored as Complex Reals
        #                  5 == 0	
        #
        #                  Note: Mode 2 is the normal mode used in
        #                        the CCP4 programs. Other modes than 2 and 0
        #                        may NOT WORK        
        MODE = temp_int32[3]
        dtype = ["int8", "int16", "float32", None, "complex64", "int8"][MODE]
        if MODE == 3:
            log.log_and_raise_error(logger, "Map file data type \"MODE=%i\" is not implemented yet." % MODE)
        if MODE not in [0,1,2,5]:
            log.log_warning(logger, "Map file data type \"MODE=%i\" not supported yet and may not work reliably." % MODE)
        #11      X length        Cell Dimensions (Angstroms)
        #12      Y length                     "
        #13      Z length                     "
        dX = temp_float32[10]/float(N)*1E-10
        dY = temp_float32[11]/float(N)*1E-10
        dZ = temp_float32[12]/float(N)*1E-10
        if dX != dY or dY != dZ:
            log.log_and_raise_error(logger, "Cannot read a map with unequal voxel dimensions")
        #17      MAPC            Which axis corresponds to Cols.  (1,2,3 for X,Y,Z)
        #18      MAPR            Which axis corresponds to Rows   (1,2,3 for X,Y,Z)
        #19      MAPS            Which axis corresponds to Sects. (1,2,3 for X,Y,Z)
        MAPC = temp_int32[16]
        MAPR = temp_int32[17]
        MAPS = temp_int32[18]
        #24      NSYMBT          Number of bytes used for storing symmetry operators
        NSYMBT = temp_int32[23]
        if NSYMBT > 0:
            log.log_and_raise_error(logger, "Omitting symmetry operations in map file.")
            f.read(NSYMBT)
        # The remaining bytes are data
        raw_data = f.read()
        raw_data = numpy.frombuffer(raw_data, dtype=dtype)
        # Now we need to project onto the right Z-Y-X array grid
        S,R,C = numpy.meshgrid(numpy.arange(NS), numpy.arange(NR), numpy.arange(NC), indexing='ij')
        S = S.flatten()
        R = R.flatten()
        C = C.flatten()
        if MAPC == 1:
            X = C
            Xlen = NC
        elif MAPC == 2:
            Y = C
            Ylen = NC
        elif MAPC == 3:
            Z = C
            Zlen = NC
        if MAPR == 1:
            X = R
            Xlen = NR
        elif MAPR == 2:
            Y = R
            Ylen = NR
        elif MAPR == 3:
            Z = R
            Zlen = NR
        if MAPS == 1:
            X = S
            Xlen = NS
        elif MAPS == 2:
            Y = S
            Ylen = NS
        elif MAPS == 3:
            Z = S
            Zlen = NS
        i = Z*(Ylen*Xlen) + Y*(Xlen) + X
        i.sort()
        data = numpy.zeros(Zlen*Ylen*Xlen, dtype=dtype)
        data[:] = raw_data[i]
        data = data.reshape((Zlen,Ylen,Xlen))
    return data, dX
Exemplo n.º 32
0
def _conf_to_spsim_opts(D_source,
                        D_particle,
                        D_detector,
                        ndim=2,
                        qn=None,
                        qmax=None):
    if ndim == 2:
        if qn is not None or qmax is not None:
            log_warning(
                logger,
                "As ndim=2 the passed values for qn and qmax take no effect.")
    if ndim == 3:
        if qn is None and qmax is None:
            log_and_raise_error(
                logger, "As ndim=3 both qn and qmax must be not None.")
            return
    import spsim
    # Create temporary file for pdb file
    tmpf_pdb = tempfile.NamedTemporaryFile(mode='w+b',
                                           bufsize=-1,
                                           suffix='.conf',
                                           prefix='tmp_spsim',
                                           dir=None,
                                           delete=False)
    tmpf_pdb_name = tmpf_pdb.name
    tmpf_pdb.close()
    # Write pdb file
    mol = spsim.get_molecule_from_atoms(D_particle["atomic_numbers"],
                                        D_particle["atomic_positions"])
    spsim.write_pdb_from_mol(tmpf_pdb_name, mol)
    spsim.free_mol(mol)
    # Start with default spsim configuration
    opts = spsim.set_defaults()
    # Create temporary file for spsim configuration
    tmpf_conf = tempfile.NamedTemporaryFile(mode='w+b',
                                            bufsize=-1,
                                            suffix='.conf',
                                            prefix='tmp_spsim',
                                            dir=None,
                                            delete=False)
    # Write string sequence from configuration dicts
    s = []
    s += "# THIS FILE WAS CREATED AUTOMATICALLY BY CONDOR\n"
    s += "# Temporary configuration file for spsim\n"
    s += "verbosity_level = 0;\n"
    s += "number_of_dimensions = %i;\n" % ndim
    s += "number_of_patterns = 1;\n"
    s += "origin_to_com = 1;\n"
    s += "input_type = \"pdb\";\n"
    #s += "pdb_filename = \"%s\";\n" % D_particle["pdb_filename"]
    s += "pdb_filename = \"%s\";\n" % tmpf_pdb_name
    if ndim == 2:
        D = D_detector["distance"]
        Lx = D_detector["pixel_size"] * D_detector["nx"]
        Ly = D_detector["pixel_size"] * D_detector["ny"]
    else:
        k0 = 2. * numpy.pi / D_source["wavelength"]
        D = qn / 2. * D_detector["pixel_size"] * k0 / qmax
        Lx = Ly = Lz = D_detector["pixel_size"] * qn
    s += "detector_distance = %.12e;\n" % D
    s += "detector_width = %.12e;\n" % Lx
    s += "detector_height = %.12e;\n" % Ly
    if ndim == 3:
        s += "detector_depth = %.12e;\n" % Lz
    s += "detector_pixel_width = %.12e;\n" % D_detector["pixel_size"]
    s += "detector_pixel_height = %.12e;\n" % D_detector["pixel_size"]
    if ndim == 3:
        s += "detector_pixel_depth = %.12e;\n" % D_detector["pixel_size"]
    if ndim == 2:
        s += "detector_center_x = %.12e;\n" % (D_detector["pixel_size"] *
                                               (D_detector["cx"] -
                                                (D_detector["nx"] - 1) / 2.))
        s += "detector_center_y = %.12e;\n" % (D_detector["pixel_size"] *
                                               (D_detector["cy"] -
                                                (D_detector["ny"] - 1) / 2.))
    else:
        s += "detector_center_x = 0;\n"
        s += "detector_center_y = 0;\n"
        s += "detector_center_z = 0;\n"
    s += "detector_binning = 1;\n"
    s += "experiment_wavelength = %.12e;\n" % D_source["wavelength"]
    s += "experiment_beam_intensity = %.12e;\n" % D_particle["intensity"]
    s += "experiment_polarization = \"ignore\";\n"  # polarization correction will be done in Condor if needed (see experiment.py)
    #s += "use_cuda = 0;\n"
    intrinsic_rotation = condor.utils.rotation.Rotation(
        values=D_particle["extrinsic_quaternion"], formalism="quaternion")
    intrinsic_rotation.invert()
    e0, e1, e2 = intrinsic_rotation.get_as_euler_angles("zxz")
    if not numpy.isfinite(e0):
        print "ERROR: phi is not finite"
    if not numpy.isfinite(e1):
        print "ERROR: theta is not finite"
    if not numpy.isfinite(e2):
        print "ERROR: psi is not finite"
    s += "phi = %.12e;\n" % e0
    s += "theta = %.12e;\n" % e1
    s += "psi = %.12e;\n" % e2
    s += "random_orientation = 0;\n"
    # Write string sequence to file
    tmpf_conf.writelines(s)
    # Close temporary file
    tmpf_conf_name = tmpf_conf.name
    tmpf_conf.close()
    # Read configuration into options struct
    spsim.read_options_file(tmpf_conf_name, opts)
    # This deletes the temporary files
    os.unlink(tmpf_pdb_name)
    os.unlink(tmpf_conf_name)
    return opts
Exemplo n.º 33
0
def read_map(filename):
    log.log_info(logger, "Automatic scaling of EM maps may not be reliable. Please make sure to check your map after using this functionality.")
    # CCP4 map file format
    # http://www.ccp4.ac.uk/html/maplib.html
    with open(filename, "rb") as f:
        # 1024 bytes header
        header_buf = f.read(1024)
        temp_int32 = numpy.frombuffer(header_buf, dtype="int32")
        temp_float32 = numpy.frombuffer(header_buf, dtype="float32")
        #1      NC              # of Columns    (fastest changing in map)
        #2      NR              # of Rows
        #3      NS              # of Sections   (slowest changing in map)
        NC = temp_int32[0]
        NR = temp_int32[1]
        NS = temp_int32[2]
        if NC != NR or NR != NS:
            log.log_and_raise_error(logger, "Cannot read a map with unequal dimensions")
        N = NC
        #4      MODE            Data type
        #                  0 = envelope stored as signed bytes (from
        #                      -128 lowest to 127 highest)
        #                  1 = Image     stored as Integer*2
        #                  2 = Image     stored as Reals
        #                  3 = Transform stored as Complex Integer*2
        #                  4 = Transform stored as Complex Reals
        #                  5 == 0	
        #
        #                  Note: Mode 2 is the normal mode used in
        #                        the CCP4 programs. Other modes than 2 and 0
        #                        may NOT WORK        
        MODE = temp_int32[3]
        dtype = ["int8", "int16", "float32", None, "complex64", "int8"][MODE]
        if MODE == 3:
            log.log_and_raise_error(logger, "Map file data type \"MODE=%i\" is not implemented yet." % MODE)
        if MODE not in [0,1,2,5]:
            log.log_warning(logger, "Map file data type \"MODE=%i\" not supported yet and may not work reliably." % MODE)
        #11      X length        Cell Dimensions (Angstroms)
        #12      Y length                     "
        #13      Z length                     "
        dX = temp_float32[10]/float(N)*1E-10
        dY = temp_float32[11]/float(N)*1E-10
        dZ = temp_float32[12]/float(N)*1E-10
        if dX != dY or dY != dZ:
            log.log_and_raise_error(logger, "Cannot read a map with unequal voxel dimensions")
        #17      MAPC            Which axis corresponds to Cols.  (1,2,3 for X,Y,Z)
        #18      MAPR            Which axis corresponds to Rows   (1,2,3 for X,Y,Z)
        #19      MAPS            Which axis corresponds to Sects. (1,2,3 for X,Y,Z)
        MAPC = temp_int32[16]
        MAPR = temp_int32[17]
        MAPS = temp_int32[18]
        #24      NSYMBT          Number of bytes used for storing symmetry operators
        NSYMBT = temp_int32[23]
        if NSYMBT > 0:
            log.log_and_raise_error(logger, "Omitting symmetry operations in map file.")
            f.read(NSYMBT)
        # The remaining bytes are data
        raw_data = f.read()
        raw_data = numpy.frombuffer(raw_data, dtype=dtype)
        # Now we need to project onto the right Z-Y-X array grid
        S,R,C = numpy.meshgrid(numpy.arange(NS), numpy.arange(NR), numpy.arange(NC), indexing='ij')
        S = S.flatten()
        R = R.flatten()
        C = C.flatten()
        if MAPC == 1:
            X = C
            Xlen = NC
        elif MAPC == 2:
            Y = C
            Ylen = NC
        elif MAPC == 3:
            Z = C
            Zlen = NC
        if MAPR == 1:
            X = R
            Xlen = NR
        elif MAPR == 2:
            Y = R
            Ylen = NR
        elif MAPR == 3:
            Z = R
            Zlen = NR
        if MAPS == 1:
            X = S
            Xlen = NS
        elif MAPS == 2:
            Y = S
            Ylen = NS
        elif MAPS == 3:
            Z = S
            Zlen = NS
        i = Z*(Ylen*Xlen) + Y*(Xlen) + X
        i.sort()
        data = numpy.zeros(Zlen*Ylen*Xlen, dtype=dtype)
        data[:] = raw_data[i]
        data = data.reshape((Zlen,Ylen,Xlen))
    return data, dX
Exemplo n.º 34
0
def analyse_particles(image, image_raw, saturation_mask, i_labels, labels, x,
                      y, merged, n_particles_max, full_output,
                      **conf_analysis):

    if full_output:
        masked_image = np.zeros_like(image_raw)
        if conf_analysis["integration_mode"] == "windows":
            thumbnails = np.zeros(shape=(n_particles_max,
                                         conf_analysis["window_size"],
                                         conf_analysis["window_size"]),
                                  dtype=image.dtype)
        else:
            thumbnails = np.zeros(shape=(n_particles_max,
                                         THUMBNAILS_WINDOW_SIZE_DEFAULT,
                                         THUMBNAILS_WINDOW_SIZE_DEFAULT),
                                  dtype=image.dtype)
    else:
        masked_image = None
        thumbnails = None
    mask = None

    N = len(i_labels)

    psuccess = np.zeros(N, dtype='bool')
    psum = np.zeros(N) - 1
    pmin = np.zeros(N) - 1
    pmax = np.zeros(N) - 1
    pmean = np.zeros(N) - 1
    pmedian = np.zeros(N) - 1

    psat = np.zeros(N) - 1

    psize = np.zeros(N) - 1
    pecc = np.zeros(N) - 1
    pcir = np.zeros(N) - 1

    for i, i_label, x_i, y_i, m in zip(range(N), i_labels, x, y, merged):

        if x_i < 0 or y_i < 0:
            continue

        # Analyse
        pixels = i_label == labels
        psat[i] = (pixels * saturation_mask).any()
        psize[i] = pixels.sum()
        pecc[i] = measure_eccentricity(intensity=image * pixels, mask=pixels)
        pcir[i] = measure_circumference(pixels)

        if conf_analysis["integration_mode"] == "windows":
            values = get_values_window(
                image_raw,
                int(round(x_i)),
                int(round(y_i)),
                window_size=conf_analysis["window_size"],
                circle_window=conf_analysis["circle_window"],
                i=i,
                masked_image=masked_image,
                thumbnails=thumbnails)
        elif conf_analysis["integration_mode"] == "labels":
            values = get_values_label(image_raw,
                                      labels,
                                      i_label,
                                      masked_image=masked_image,
                                      thumbnails=thumbnails)
        else:
            log_and_raise_error(
                logger, "%s is not a valid integration_mode!" %
                conf_analysis["integration_mode"])

        if values is not None and len(values) > 0:
            psuccess[i] = True
            psum[i] = values.sum()
            pmin[i] = values.min()
            pmax[i] = values.max()
            pmean[i] = values.mean()
            pmedian[i] = np.median(values)

    success = True
    return success, psuccess, psum, pmean, pmedian, pmin, pmax, psize, psat, pecc, pcir, masked_image, thumbnails
Exemplo n.º 35
0
Arquivo: detect.py Projeto: zbsun/spts
def find_particles(image_scored,
                   image_thresholded,
                   min_dist,
                   n_particles_max,
                   peak_centering="center_of_mass"):

    n_lit = image_thresholded.sum()
    log_debug(logger, "%i pixels above threshold" % n_lit)

    success = False
    return_default = success, [], None, None, None, None, None, None, None, None

    if n_lit == 0:
        return return_default

    else:
        log_debug(logger, "Label image")
        labels, n_labels = scipy.ndimage.measurements.label(image_thresholded)
        i_labels = range(1, n_labels + 1)

        if n_labels > n_particles_max:
            log_info(
                logger,
                "%i labels - (frame overexposed? too many particles?), skipping analysis"
                % n_labels)
            return return_default

        V = [image_scored[i_label == labels].max() for i_label in i_labels]

        nx = image_thresholded.shape[1]
        ny = image_thresholded.shape[0]
        x, y = np.meshgrid(np.arange(nx), np.arange(ny))
        x = x[image_thresholded]
        y = y[image_thresholded]
        l = labels[image_thresholded]
        v = image_scored[image_thresholded]

        if peak_centering == "center_of_mass":
            log_debug(logger, "Determine centers of mass")
            com = scipy.ndimage.measurements.center_of_mass(
                image_thresholded, labels, i_labels)
            X = [com_x for com_y, com_x in com]
            Y = [com_y for com_y, com_x in com]

        elif peak_centering == "center_to_max":
            log_debug(logger, "Determine maximum positions")
            X = []
            Y = []
            for i_label in i_labels:
                i_max = (v * (l == i_label)).argmax()
                X.append(x[i_max])
                Y.append(y[i_max])
        else:
            log_and_raise_error(
                logger, "%s is not a valid argument for peak_centering!" %
                peak_centering)

        dislocation = []
        for i_label, xc, yc in zip(i_labels, X, Y):
            i_max = (v * (l == i_label)).argmax()
            dislocation.append(np.sqrt((x[i_max] - xc)**2 +
                                       (y[i_max] - yc)**2))

        merged = list(np.zeros(len(i_labels), dtype=np.bool))

        # Merge too close peaks
        log_debug(logger, "Merge too close points")
        i_labels, labels, X, Y, V, merged, dists_closest_neighbor = merge_close_points(
            i_labels, labels, X, Y, V, merged, min_dist)
        log_debug(logger, "Clean up labels")
        i_labels, labels = clean_up_labels(i_labels, labels)
        n_labels = len(i_labels)

        log_debug(logger, "Measure size of each peak")
        areas = measure_areas(i_labels, labels)

        success = True
        areas = np.asarray(areas)
        X = np.asarray(X)
        Y = np.asarray(Y)
        dislocation = np.asarray(dislocation)
        V = np.asarray(V)
        merged = np.asarray(merged)
        dists_closest_neighbor = np.asarray(dists_closest_neighbor)

        return success, i_labels, labels, areas, X, Y, V, merged, dists_closest_neighbor, dislocation