Ejemplo n.º 1
0
def calculate_fxs_diffraction_pattern_gpu(reciprocal_space, particle, coords, return_type='intensity'):
    """
    Calculate the diffraction field of the specified reciprocal space.

    :param reciprocal_space: The reciprocal space over which to calculate the diffraction field.
    :param particle: The particle object to calculate the diffraction field.
    :param return_type: 'intensity' to return the intensity field. 'complex_field' to return the full diffraction field.
    :return: The diffraction field.
    """
    """This function can be used to calculate the diffraction field for
    arbitrary reciprocal space """
    # convert the reciprocal space into a 1d series.
    shape = reciprocal_space.shape
    pixel_number = np.prod(shape[:-1])
    reciprocal_space_1d = np.reshape(reciprocal_space, [pixel_number, 3])
    reciprocal_norm_1d = np.sqrt(np.sum(np.square(reciprocal_space_1d), axis=-1))

    # Calculate atom form factor for the reciprocal space
    form_factor = pd.calculate_atomic_factor(particle=particle,
                                             q_space=reciprocal_norm_1d * (1e-10 / 2.),  # For unit compatibility
                                             pixel_num=pixel_number)

    # Get atom position
    print ("particle.atom_pos[:].shape", particle.atom_pos[:].shape)
    print ("coords.shape", coords.shape)
    atom_position = np.ascontiguousarray(particle.atom_pos[:]+coords)
    atom_type_num = len(particle.split_idx) - 1

    # create
    pattern_cos = np.zeros(pixel_number, dtype=np.float64)
    pattern_sin = np.zeros(pixel_number, dtype=np.float64)

    # atom_number = atom_position.shape[0]
    split_index = np.array(particle.split_idx)

    cuda_split_index = cuda.to_device(split_index)
    cuda_atom_position = cuda.to_device(atom_position)
    cuda_reciprocal_position = cuda.to_device(reciprocal_space_1d)
    cuda_form_factor = cuda.to_device(form_factor)

    # Calculate the pattern
    calculate_pattern_gpu_back_engine[(pixel_number + 511) // 512, 512](
        cuda_form_factor, cuda_reciprocal_position, cuda_atom_position,
        pattern_cos, pattern_sin, atom_type_num, cuda_split_index,
        pixel_number)

    if return_type == "intensity":
        pattern = np.reshape(np.square(np.abs(pattern_cos + 1j * pattern_sin)), shape[:-1])
        return pattern
    elif return_type == "complex_field":
        pattern = np.reshape(pattern_cos + 1j * pattern_sin, shape[:-1])
        return pattern
    else:
        print("Please set the parameter return_type = 'intensity' or 'complex_field'")
        print("This time, this program return the complex field.")
        return np.reshape(pattern_cos + 1j * pattern_sin, shape[:-1])
Ejemplo n.º 2
0
def calculate_diffraction_pattern_gpu(reciprocal_space,
                                      particle,
                                      return_type='intensity'):
    """
    Calculate the diffraction field of the specified reciprocal space.

    :param reciprocal_space: The reciprocal space over which to calculate the diffraction field.
    :param particle: The particle object to calculate the diffraction field.
    :param return_type: 'intensity' to return the intensity field. 'complex_field' to return the full diffraction field.
    :return: The diffraction field.
    """
    """This function can be used to calculate the diffraction field for
    arbitrary reciprocal space """
    # convert the reciprocal space into a 1d series.
    shape = reciprocal_space.shape
    pixel_number = int(np.prod(shape[:-1]))
    reciprocal_space_1d = xp.reshape(reciprocal_space, [pixel_number, 3])
    reciprocal_norm_1d = xp.sqrt(
        xp.sum(xp.square(reciprocal_space_1d), axis=-1))

    # Calculate atom form factor for the reciprocal space
    form_factor = pd.calculate_atomic_factor(
        particle=particle,
        q_space=reciprocal_norm_1d * (1e-10 / 2.),  # For unit compatibility
        pixel_num=pixel_number)

    # Get atom position
    atom_position = np.ascontiguousarray(particle.atom_pos[:])
    atom_type_num = len(particle.split_idx) - 1

    # create
    pattern_cos = xp.zeros(pixel_number, dtype=xp.float64)
    pattern_sin = xp.zeros(pixel_number, dtype=xp.float64)

    # atom_number = atom_position.shape[0]
    split_index = xp.array(particle.split_idx)

    cuda_split_index = cuda.to_device(split_index)
    cuda_atom_position = cuda.to_device(atom_position)
    cuda_reciprocal_position = cuda.to_device(reciprocal_space_1d)
    cuda_form_factor = cuda.to_device(form_factor)

    # Calculate the pattern
    calculate_pattern_gpu_back_engine[(pixel_number + 511) // 512,
                                      512](cuda_form_factor,
                                           cuda_reciprocal_position,
                                           cuda_atom_position, pattern_cos,
                                           pattern_sin, atom_type_num,
                                           cuda_split_index, pixel_number)

    # Add the hydration layer
    if particle.mesh is not None:
        water_position = np.ascontiguousarray(
            particle.mesh[particle.solvent_mask, :])
        water_num = np.sum(particle.solvent_mask)
        water_prefactor = particle.solvent_mean_electron_density * particle.mesh_voxel_size**3

        cuda_water_position = cuda.to_device(water_position)

        calculate_solvent_pattern_gpu_back_engine[(pixel_number + 511) // 512,
                                                  512](
                                                      cuda_reciprocal_position,
                                                      cuda_water_position,
                                                      pattern_cos, pattern_sin,
                                                      water_prefactor,
                                                      water_num, pixel_number)

    if return_type == "intensity":
        pattern = np.reshape(np.square(np.abs(pattern_cos + 1j * pattern_sin)),
                             shape[:-1])
        return xp.asarray(pattern)
    elif return_type == "complex_field":
        pattern = np.reshape(pattern_cos + 1j * pattern_sin, shape[:-1])
        return xp.asarray(pattern)
    else:
        print(
            "Please set the parameter return_type = 'intensity' or 'complex_field'"
        )
        print("This time, this program return the complex field.")
        pattern = np.reshape(pattern_cos + 1j * pattern_sin, shape[:-1])
        return xp.asarray(pattern)