Ejemplo n.º 1
0
def _get_points_within_radius(point,
                              radius,
                              radius_step=0.2,
                              angle_step=pi / 5):
    """
  Generates a list of points and their associated radius in steps around a
  sphere.

  Parameters
  ----------
  point : tuple of float, float, float
      X, Y, Z, coordinates to center the sampling around.
  radius : float
      Max radius around the center to sample.
  radius_step : float, optional
      Steps along the radius to use when sampling.
  angle_step : float, optional
      Steps around each radii distance to use when sampling. Amount is in
      radians.

  Returns
  -------
  list of tuple of float, float, float
      List of points to be sampled.
  list of float
      List of radii corresponding to each point.
  """

    points = [point]
    radiuses = [0]
    for r in xfrange(radius_step, radius, radius_step):
        for theta in xfrange(-pi, pi, angle_step):
            for phi in xfrange(-pi, pi, angle_step):
                x = r * cos(theta) * sin(phi) + point[0]
                y = r * sin(theta) * sin(phi) + point[1]
                z = r * cos(phi) + point[2]
                points.append((x, y, z))
                radiuses.append(r)

    return points, radiuses
Ejemplo n.º 2
0
def _get_points_within_radius(point, radius, radius_step=0.2, angle_step=pi / 5):
    """
  Generates a list of points and their associated radius in steps around a
  sphere.

  Parameters
  ----------
  point : tuple of float, float, float
      X, Y, Z, coordinates to center the sampling around.
  radius : float
      Max radius around the center to sample.
  radius_step : float, optional
      Steps along the radius to use when sampling.
  angle_step : float, optional
      Steps around each radii distance to use when sampling. Amount is in
      radians.

  Returns
  -------
  list of tuple of float, float, float
      List of points to be sampled.
  list of float
      List of radii corresponding to each point.
  """

    points = [point]
    radiuses = [0]
    for r in xfrange(radius_step, radius, radius_step):
        for theta in xfrange(-pi, pi, angle_step):
            for phi in xfrange(-pi, pi, angle_step):
                x = r * cos(theta) * sin(phi) + point[0]
                y = r * sin(theta) * sin(phi) + point[1]
                z = r * cos(phi) + point[2]
                points.append((x, y, z))
                radiuses.append(r)

    return points, radiuses
Ejemplo n.º 3
0
 def structure_factors(self, max_cycles=10):
   """P. van der Sluis and A. L. Spek, Acta Cryst. (1990). A46, 194-201."""
   assert self.mask is not None
   if self.n_voids() == 0: return
   if self.use_set_completion:
     f_calc_set = self.complete_set
   else:
     f_calc_set = self.fo2.set()
   self.f_calc = f_calc_set.structure_factors_from_scatterers(
     self.xray_structure, algorithm="direct").f_calc()
   f_obs = self.f_obs()
   self.scale_factor = flex.sum(f_obs.data())/flex.sum(
     flex.abs(self.f_calc.data()))
   f_obs_minus_f_calc = f_obs.f_obs_minus_f_calc(
     1/self.scale_factor, self.f_calc)
   self.fft_scale = self.xray_structure.unit_cell().volume()\
       / self.crystal_gridding.n_grid_points()
   epsilon_for_min_residual = 2
   for i in range(max_cycles):
     self.diff_map = miller.fft_map(self.crystal_gridding, f_obs_minus_f_calc)
     self.diff_map.apply_volume_scaling()
     stats = self.diff_map.statistics()
     masked_diff_map = self.diff_map.real_map_unpadded().set_selected(
       self.mask.data.as_double() == 0, 0)
     n_solvent_grid_points = self.n_solvent_grid_points()
     for j in range(self.n_voids()):
       # exclude voids with negative electron counts from the masked map
       # set the electron density in those areas to be zero
       selection = self.mask.data == j+2
       if self.exclude_void_flags[j]:
         masked_diff_map.set_selected(selection, 0)
         continue
       diff_map_ = masked_diff_map.deep_copy().set_selected(~selection, 0)
       f_000 = flex.sum(diff_map_) * self.fft_scale
       f_000_s = f_000 * (
         self.crystal_gridding.n_grid_points() /
         (self.crystal_gridding.n_grid_points() - n_solvent_grid_points))
       if f_000_s < 0:
         masked_diff_map.set_selected(selection, 0)
         f_000_s = 0
         self.exclude_void_flags[j] = True
     self.f_000 = flex.sum(masked_diff_map) * self.fft_scale
     f_000_s = self.f_000 * (masked_diff_map.size() /
       (masked_diff_map.size() - self.n_solvent_grid_points()))
     if (self.f_000_s is not None and
         approx_equal_relatively(self.f_000_s, f_000_s, 0.0001)):
       break # we have reached convergence
     else:
       self.f_000_s = f_000_s
     masked_diff_map.add_selected(
       self.mask.data.as_double() > 0,
       self.f_000_s/self.xray_structure.unit_cell().volume())
     if 0:
       from crys3d import wx_map_viewer
       wx_map_viewer.display(
         title="masked diff_map",
         raw_map=masked_diff_map.as_double(),
         unit_cell=f_obs.unit_cell())
     self._f_mask = f_obs.structure_factors_from_map(map=masked_diff_map)
     self._f_mask *= self.fft_scale
     scales = []
     residuals = []
     min_residual = 1000
     for epsilon in xfrange(epsilon_for_min_residual, 0.9, -0.2):
       f_model_ = self.f_model(epsilon=epsilon)
       scale = flex.sum(f_obs.data())/flex.sum(flex.abs(f_model_.data()))
       residual = flex.sum(flex.abs(
         1/scale * flex.abs(f_obs.data())- flex.abs(f_model_.data()))) \
                / flex.sum(1/scale * flex.abs(f_obs.data()))
       scales.append(scale)
       residuals.append(residual)
       min_residual = min(min_residual, residual)
       if min_residual == residual:
         scale_for_min_residual = scale
         epsilon_for_min_residual = epsilon
     self.scale_factor = scale_for_min_residual
     f_model = self.f_model(epsilon=epsilon_for_min_residual)
     f_obs = self.f_obs()
     f_obs_minus_f_calc = f_obs.phase_transfer(f_model).f_obs_minus_f_calc(
       1/self.scale_factor, self.f_calc)
   return self._f_mask
Ejemplo n.º 4
0
    def structure_factors(self, max_cycles=10):
        """P. van der Sluis and A. L. Spek, Acta Cryst. (1990). A46, 194-201."""
        assert self.mask is not None
        if self.n_voids() == 0:
            return
        if self.use_set_completion:
            f_calc_set = self.complete_set
        else:
            f_calc_set = self.fo2.set()
        self.f_calc = f_calc_set.structure_factors_from_scatterers(self.xray_structure, algorithm="direct").f_calc()
        f_obs = self.f_obs()
        self.scale_factor = flex.sum(f_obs.data()) / flex.sum(flex.abs(self.f_calc.data()))
        f_obs_minus_f_calc = f_obs.f_obs_minus_f_calc(1 / self.scale_factor, self.f_calc)
        self.fft_scale = self.xray_structure.unit_cell().volume() / self.crystal_gridding.n_grid_points()
        epsilon_for_min_residual = 2
        for i in range(max_cycles):
            self.diff_map = miller.fft_map(self.crystal_gridding, f_obs_minus_f_calc)
            self.diff_map.apply_volume_scaling()
            stats = self.diff_map.statistics()
            masked_diff_map = self.diff_map.real_map_unpadded().set_selected(self.mask.data.as_double() == 0, 0)
            n_solvent_grid_points = self.n_solvent_grid_points()
            for j in range(self.n_voids()):
                # exclude voids with negative electron counts from the masked map
                # set the electron density in those areas to be zero
                selection = self.mask.data == j + 2
                if self.exclude_void_flags[j]:
                    masked_diff_map.set_selected(selection, 0)
                    continue
                diff_map_ = masked_diff_map.deep_copy().set_selected(~selection, 0)
                f_000 = flex.sum(diff_map_) * self.fft_scale
                f_000_s = f_000 * (
                    self.crystal_gridding.n_grid_points()
                    / (self.crystal_gridding.n_grid_points() - n_solvent_grid_points)
                )
                if f_000_s < 0:
                    masked_diff_map.set_selected(selection, 0)
                    f_000_s = 0
                    self.exclude_void_flags[j] = True
            self.f_000 = flex.sum(masked_diff_map) * self.fft_scale
            f_000_s = self.f_000 * (masked_diff_map.size() / (masked_diff_map.size() - self.n_solvent_grid_points()))
            if self.f_000_s is not None and approx_equal_relatively(self.f_000_s, f_000_s, 0.0001):
                break  # we have reached convergence
            else:
                self.f_000_s = f_000_s
            masked_diff_map.add_selected(
                self.mask.data.as_double() > 0, self.f_000_s / self.xray_structure.unit_cell().volume()
            )
            if 0:
                from crys3d import wx_map_viewer

                wx_map_viewer.display(
                    title="masked diff_map", raw_map=masked_diff_map.as_double(), unit_cell=f_obs.unit_cell()
                )
            self._f_mask = f_obs.structure_factors_from_map(map=masked_diff_map)
            self._f_mask *= self.fft_scale
            scales = []
            residuals = []
            min_residual = 1000
            for epsilon in xfrange(epsilon_for_min_residual, 0.9, -0.2):
                f_model_ = self.f_model(epsilon=epsilon)
                scale = flex.sum(f_obs.data()) / flex.sum(flex.abs(f_model_.data()))
                residual = flex.sum(
                    flex.abs(1 / scale * flex.abs(f_obs.data()) - flex.abs(f_model_.data()))
                ) / flex.sum(1 / scale * flex.abs(f_obs.data()))
                scales.append(scale)
                residuals.append(residual)
                min_residual = min(min_residual, residual)
                if min_residual == residual:
                    scale_for_min_residual = scale
                    epsilon_for_min_residual = epsilon
            self.scale_factor = scale_for_min_residual
            f_model = self.f_model(epsilon=epsilon_for_min_residual)
            f_obs = self.f_obs()
            f_obs_minus_f_calc = f_obs.phase_transfer(f_model).f_obs_minus_f_calc(1 / self.scale_factor, self.f_calc)
        return self._f_mask
Ejemplo n.º 5
0
  def __init__(self, fo2, fc,
               scale_factor=None,
               outlier_cutoff_factor=None,
               probability_plot_slope=None):
    self.probability_plot_slope = probability_plot_slope
    assert fo2.is_xray_intensity_array()
    assert fc.is_complex_array()
    assert not fo2.space_group().is_centric()
    if scale_factor is None:
      scale_factor = fo2.scale_factor(fc)
    fc2 = fc.as_intensity_array()
    self.delta_fc2 = fc2.anomalous_differences()
    self.delta_fo2 = fo2.anomalous_differences()
    self.n_bijvoet_pairs = self.delta_fo2.size()
    if outlier_cutoff_factor is not None:
      cutoff_sel = flex.abs(self.delta_fo2.data()) > (
        outlier_cutoff_factor * scale_factor) * flex.max(
          flex.abs(self.delta_fc2.data()))
      self.delta_fo2 = self.delta_fo2.select(~cutoff_sel)
      self.delta_fc2 = self.delta_fc2.select(~cutoff_sel)
    self.delta_fc2 = self.delta_fc2.customized_copy(
      data=self.delta_fc2.data() * scale_factor)
    if not self.delta_fo2.size():
      raise Sorry("Absolute structure could not be determined")
    min_gamma = -10
    max_gamma = 10

    # quick and dirty to find better min, max gammas
    max_log_p_obs = -1e100
    while True:
      # search for the maximum
      width = max_gamma - min_gamma
      if width < 0.0001:
        break
      middle = (min_gamma + max_gamma)/2
      a = middle - width/4
      b = middle + width/4
      value_a = self.log_p_obs_given_gamma(a)
      value_b = self.log_p_obs_given_gamma(b)
      if value_a > value_b:
        max_gamma = middle
      elif value_a == value_b:
        min_gamma = a
        max_gamma = b
      else:
        min_gamma = middle
      max_log_p_obs = max([max_log_p_obs, value_a, value_b])
    while True:
      # search for where the curve becomes close to zero on the left
      min_gamma = middle - width/2
      if (width > 100 or
          self.log_p_obs_given_gamma(min_gamma) - max_log_p_obs < -10):
        break
      width *= 2
    width = max_gamma - min_gamma
    while True:
      # search for where the curve becomes close to zero on the right
      max_gamma = middle + width/2
      if (width > 100 or
          self.log_p_obs_given_gamma(max_gamma) - max_log_p_obs < -10):
        break
      width *= 2

    n_steps = 500
    d_gamma = (max_gamma - min_gamma)/n_steps
    # now do it properly
    log_p_obs_given_gammas = flex.double()
    for gamma in xfrange(min_gamma, max_gamma, d_gamma):
      log_p_obs_given_gammas.append(self.log_p_obs_given_gamma(gamma))
    max_log_p_obs = flex.max(log_p_obs_given_gammas)
    G_numerator = 0
    G_denominator = 0
    p_u_gammas = flex.double()
    # Numerical integration using trapezoidal rule
    for i, gamma in enumerate(xfrange(min_gamma, max_gamma, d_gamma)):
      p_u_gamma = math.exp(log_p_obs_given_gammas[i] - max_log_p_obs)
      p_u_gammas.append(p_u_gamma)
      if i == 0: continue
      G_numerator += 0.5 * d_gamma * (
        (gamma-d_gamma) * p_u_gammas[-2] + gamma * p_u_gammas[-1])
      G_denominator += 0.5 * (p_u_gammas[-2] + p_u_gammas[-1]) * d_gamma
    self.G = G_numerator/G_denominator
    sigma_squared_G_numerator = 0
    # Numerical integration using trapezoidal rule
    next_ = None
    for i, gamma in enumerate(xfrange(min_gamma, max_gamma, d_gamma)):
      previous = next_
      next_ = math.pow((gamma - self.G), 2) * p_u_gammas[i] * d_gamma
      if i == 0: continue
      sigma_squared_G_numerator += 0.5 * (previous + next_)
    self.hooft_y = (1-self.G)/2
    self.sigma_G = math.sqrt(sigma_squared_G_numerator/G_denominator)
    self.sigma_y = self.sigma_G/2

    # Now calculate P2, P3 values
    log_p_obs_given_gamma_is_minus_1 = self.log_p_obs_given_gamma(-1)
    log_p_obs_given_gamma_is_0 = self.log_p_obs_given_gamma(0)
    log_p_obs_given_gamma_is_1 = self.log_p_obs_given_gamma(1)
    max_log_p_obs = max([log_p_obs_given_gamma_is_minus_1,
                         log_p_obs_given_gamma_is_0,
                         log_p_obs_given_gamma_is_1])
    # all values normalised by max_log_p_obs for numerical stability
    log_p_obs_given_gamma_is_minus_1 -= max_log_p_obs
    log_p_obs_given_gamma_is_0 -= max_log_p_obs
    log_p_obs_given_gamma_is_1 -= max_log_p_obs
    p2_denominator = math.exp(log_p_obs_given_gamma_is_1) \
                   + math.exp(log_p_obs_given_gamma_is_minus_1)
    p3_denominator = math.exp(log_p_obs_given_gamma_is_1) \
                   + math.exp(log_p_obs_given_gamma_is_minus_1) \
                   + math.exp(log_p_obs_given_gamma_is_0)
    #
    if p2_denominator == 0: self.p2_true = self.p2_false = None
    else:
      self.p2_true = (
        math.exp(log_p_obs_given_gamma_is_1)) / p2_denominator
      self.p2_false = (
        math.exp(log_p_obs_given_gamma_is_minus_1)) / p2_denominator
    self.p3_true = (
      math.exp(log_p_obs_given_gamma_is_1)) / p3_denominator
    self.p3_false = (
      math.exp(log_p_obs_given_gamma_is_minus_1)) / p3_denominator
    self.p3_racemic_twin = (
      math.exp(log_p_obs_given_gamma_is_0)) / p3_denominator
Ejemplo n.º 6
0
  def __init__(self, fo2, fc,
               scale_factor=None,
               outlier_cutoff_factor=None,
               probability_plot_slope=None):
    self.probability_plot_slope = probability_plot_slope
    assert fo2.is_xray_intensity_array()
    assert fc.is_complex_array()
    assert not fo2.space_group().is_centric()
    if scale_factor is None:
      scale_factor = fo2.scale_factor(fc)
    fc2 = fc.as_intensity_array()
    self.delta_fc2 = fc2.anomalous_differences()
    self.delta_fo2 = fo2.anomalous_differences()
    self.n_bijvoet_pairs = self.delta_fo2.size()
    if outlier_cutoff_factor is not None:
      cutoff_sel = flex.abs(self.delta_fo2.data()) > (
        outlier_cutoff_factor * scale_factor) * flex.max(
          flex.abs(self.delta_fc2.data()))
      self.delta_fo2 = self.delta_fo2.select(~cutoff_sel)
      self.delta_fc2 = self.delta_fc2.select(~cutoff_sel)
    self.delta_fc2 = self.delta_fc2.customized_copy(
      data=self.delta_fc2.data() * scale_factor)
    if not self.delta_fo2.size():
      raise Sorry("Absolute structure could not be determined")
    min_gamma = -10
    max_gamma = 10

    # quick and dirty to find better min, max gammas
    max_log_p_obs = -1e100
    while True:
      # search for the maximum
      width = max_gamma - min_gamma
      if width < 0.0001:
        break
      middle = (min_gamma + max_gamma)/2
      a = middle - width/4
      b = middle + width/4
      value_a = self.log_p_obs_given_gamma(a)
      value_b = self.log_p_obs_given_gamma(b)
      if value_a > value_b:
        max_gamma = middle
      elif value_a == value_b:
        min_gamma = a
        max_gamma = b
      else:
        min_gamma = middle
      max_log_p_obs = max([max_log_p_obs, value_a, value_b])
    while True:
      # search for where the curve becomes close to zero on the left
      min_gamma = middle - width/2
      if (width > 100 or
          self.log_p_obs_given_gamma(min_gamma) - max_log_p_obs < -10):
        break
      width *= 2
    width = max_gamma - min_gamma
    while True:
      # search for where the curve becomes close to zero on the right
      max_gamma = middle + width/2
      if (width > 100 or
          self.log_p_obs_given_gamma(max_gamma) - max_log_p_obs < -10):
        break
      width *= 2

    n_steps = 500
    d_gamma = (max_gamma - min_gamma)/n_steps
    # now do it properly
    log_p_obs_given_gammas = flex.double()
    for gamma in xfrange(min_gamma, max_gamma, d_gamma):
      log_p_obs_given_gammas.append(self.log_p_obs_given_gamma(gamma))
    max_log_p_obs = flex.max(log_p_obs_given_gammas)
    G_numerator = 0
    G_denominator = 0
    p_u_gammas = flex.double()
    # Numerical integration using trapezoidal rule
    for i, gamma in enumerate(xfrange(min_gamma, max_gamma, d_gamma)):
      p_u_gamma = math.exp(log_p_obs_given_gammas[i] - max_log_p_obs)
      p_u_gammas.append(p_u_gamma)
      if i == 0: continue
      G_numerator += 0.5 * d_gamma * (
        (gamma-d_gamma) * p_u_gammas[-2] + gamma * p_u_gammas[-1])
      G_denominator += 0.5 * (p_u_gammas[-2] + p_u_gammas[-1]) * d_gamma
    self.G = G_numerator/G_denominator
    sigma_squared_G_numerator = 0
    # Numerical integration using trapezoidal rule
    next = None
    for i, gamma in enumerate(xfrange(min_gamma, max_gamma, d_gamma)):
      previous = next
      next = math.pow((gamma - self.G), 2) * p_u_gammas[i] * d_gamma
      if i == 0: continue
      sigma_squared_G_numerator += 0.5 * (previous + next)
    self.hooft_y = (1-self.G)/2
    self.sigma_G = math.sqrt(sigma_squared_G_numerator/G_denominator)
    self.sigma_y = self.sigma_G/2

    # Now calculate P2, P3 values
    log_p_obs_given_gamma_is_minus_1 = self.log_p_obs_given_gamma(-1)
    log_p_obs_given_gamma_is_0 = self.log_p_obs_given_gamma(0)
    log_p_obs_given_gamma_is_1 = self.log_p_obs_given_gamma(1)
    max_log_p_obs = max([log_p_obs_given_gamma_is_minus_1,
                         log_p_obs_given_gamma_is_0,
                         log_p_obs_given_gamma_is_1])
    # all values normalised by max_log_p_obs for numerical stability
    log_p_obs_given_gamma_is_minus_1 -= max_log_p_obs
    log_p_obs_given_gamma_is_0 -= max_log_p_obs
    log_p_obs_given_gamma_is_1 -= max_log_p_obs
    p2_denominator = math.exp(log_p_obs_given_gamma_is_1) \
                   + math.exp(log_p_obs_given_gamma_is_minus_1)
    p3_denominator = math.exp(log_p_obs_given_gamma_is_1) \
                   + math.exp(log_p_obs_given_gamma_is_minus_1) \
                   + math.exp(log_p_obs_given_gamma_is_0)
    #
    if p2_denominator == 0: self.p2_true = self.p2_false = None
    else:
      self.p2_true = (
        math.exp(log_p_obs_given_gamma_is_1)) / p2_denominator
      self.p2_false = (
        math.exp(log_p_obs_given_gamma_is_minus_1)) / p2_denominator
    self.p3_true = (
      math.exp(log_p_obs_given_gamma_is_1)) / p3_denominator
    self.p3_false = (
      math.exp(log_p_obs_given_gamma_is_minus_1)) / p3_denominator
    self.p3_racemic_twin = (
      math.exp(log_p_obs_given_gamma_is_0)) / p3_denominator