Exemple #1
0
 def GetRefractionIndexDeltaBeta(self):
   """ Refraction index, n=1-delta-i*beta. returns a tuple delta,beta"""
   delta=0.0
   beta=0.0
   density=self.GetAtomDensity()
   wav=W2E(self.scatt[0].nrj)*1e-10 #assume all scatterers have same list of nrjs
   density=self.GetAtomDensity()
   for s in self.scatt:
     z = sasaki.table(s.label).atomic_number()
     fp_fdp_sasaki=sasaki.table(s.element_symbol()).at_ev(self.scatt[0].nrj)
     delta+=wav**2*density[s.label]*re/(2*pi)*(z-s.fp0)
     beta +=wav**2*density[s.label]*re/(2*pi)*s.fs0
   return delta,beta
Exemple #2
0
def get_fp_fpp_from_sasaki (guess_ha,wavelength):
  from cctbx.eltbx import sasaki
  from decimal import Decimal, ROUND_HALF_UP
  if wavelength is None or guess_ha is None :
    return None, None
  try:
    table = sasaki.table(guess_ha)
  except Exception, e :
    return None, None
Exemple #3
0
 def __init__(self,label,site,occup,u,energy,fp=None,fs=None):
   xray.scatterer.__init__(self,label=label,site=site,occupancy=occup,u=u)
   self.nrj=energy
   if fp==None or fs==None:
     fp_fdp_sasaki=sasaki.table(self.element_symbol()).at_ev(self.nrj)
     self.fp0=fp_fdp_sasaki.fp()
     self.fs0=fp_fdp_sasaki.fdp()
   else:
     self.fp0=fp0
     self.fs0=fs
def get_fo(atom_type=None, wavelength=None, out=sys.stdout):
    if not atom_type or not wavelength:
        raise Sorry("Please specify either f_double_prime or " + "atom_type and wavelength")
    from cctbx.eltbx import sasaki

    try:
        table = sasaki.table(atom_type)
        fo = table.atomic_number()
    except ValueError:
        raise Sorry("Unable to get scattering factors for %s" % (atom_type))
    return fo
Exemple #5
0
def anonymize_ions(pdb_hierarchy, log=sys.stdout):
    """
  Convert any elemental ions in the PDB hierarchy to water, resetting the
  occupancy and scaling the B-factor.  The atom segids will be set to the old
  resname.  NOTE: this does not change the corresponding scatterer in the xray
  structure, but a new xray structure can be obtained by calling
  hierarchy.extract_xray_structure(crystal_symmetry).

  Parameters
  ----------
  pdb_hierarchy : iotbx.pdb.hierarchy.root
  log : file, optional

  Returns
  -------
  iotbx.pdb.hierarchy.root
      New pdb hierarchy with its ions anonymized
  int
      Number of atoms that were anonymized.
  """
    ion_resnames = set(chemical_elements.proper_upper_list())
    for resname in server.params["_lib_charge.resname"]:
        if resname not in WATER_RES_NAMES:
            ion_resnames.add(resname)
    n_converted = 0
    pdb_hierarchy = pdb_hierarchy.deep_copy()
    for model in pdb_hierarchy.models():
        for chain in model.chains():
            for residue_group in chain.residue_groups():
                for atom_group in residue_group.atom_groups():
                    if atom_group.resname.strip() in ion_resnames:
                        atoms = atom_group.atoms()
                        id_strs = []
                        for atom in atoms:
                            elem = atom.element.strip()
                            if elem in ["H", "D"]:
                                atomic_number = 1
                            elif elem in ["HE"]:
                                atomic_number = 2
                            else:
                                atomic_number = sasaki.table(elem).atomic_number()
                            id_strs.append(atom.id_str())
                            atom.segid = atom_group.resname
                            atom.name = " O  "
                            atom.element = "O"
                            atom.charge = ""
                            atom.occupancy = 1.0
                            atom.b = atom.b * (10 / atomic_number)
                        atom_group.resname = "HOH"
                        for atom, id_str in zip(atoms, id_strs):
                            print >> log, "%s --> %s, B-iso = %.2f" % (id_str, atom.id_str(), atom.b)
                            n_converted += 1
    return pdb_hierarchy, n_converted
def get_fp_fdp(atom_type=None,wavelength=None,out=sys.stdout):
  if not atom_type or not wavelength:
    raise Sorry("Please specify either f_double_prime or " +
      "atom_type and wavelength")
  from cctbx.eltbx import sasaki
  try:
    table = sasaki.table(atom_type)
    fp_fdp = table.at_angstrom(wavelength)
  except ValueError :
    raise Sorry("Unable to get scattering factors for %s" %(atom_type))
  if fp_fdp.is_valid():
    return fp_fdp
  else:
    return None
Exemple #7
0
def guess_the_atom(hklin, nsites):
  '''Guess the atom which gives rise to the observed anomalous differences
  in intensities (i.e. I(+) and I(-)) though CCTBX code internally computes
  F(+) etc.'''

  mtz_obj = mtz.object(hklin)
  mi = mtz_obj.extract_miller_indices()

  sg = mtz_obj.space_group()

  for crystal in mtz_obj.crystals():
    if crystal.name() != 'HKL_base':
      uc = crystal.unit_cell()

  n_ops = len(sg.all_ops())
  v_asu = uc.volume() / n_ops
  mw = v_asu / 2.7

  atoms = ['Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Se', 'Br', 'S', 'P']

  tables = [sasaki.table(atom) for atom in atoms]

  for crystal in mtz_obj.crystals():
    if crystal.name() == 'HKL_base':
      continue
    assert(len(crystal.datasets()) == 1)
    for dataset in crystal.datasets():
      wavelength = dataset.wavelength()

  energy = wavelength_energy(wavelength)

  mas = mtz_obj.as_miller_arrays()

  best_atom = None
  best_diff = 100.0

  for ma in mas:
    columns = ma.info().label_string()
    if 'I(+)' in columns and 'I(-)' in columns:
      signal = ma.anomalous_signal()
      for j, atom in enumerate(atoms):
        for energy_offset in (-100.0, 0.0, 100.0):
          wavelength = wavelength_energy(energy + energy_offset)
          fdp = tables[j].at_angstrom(wavelength).fdp()
          p_signal = fdp * math.sqrt(nsites / mw)
          if math.fabs(p_signal - signal) < best_diff:
            best_diff = math.fabs(p_signal - signal)
            best_atom = atom

  return best_atom
Exemple #8
0
def ion_anomalous_vector(scatter_env, elements=None, ratios=True,
                         anom_peak=False):
  """
  Creates a vector of the anomalous features of a site. These can either include
  the f'' / f''_expected for a variety of ion identities or the exact anomalous
  peak height.

  Parameters
  ----------
  scatter_env : mmtbx.ions.environment.ScatteringEnvironment
      An object containing information about the scattering environment at a
      site.
  elements : list of str, optional
      List of elements to include when calculating f''_expected values. If
      unset, takes the list from mmtbx.ions.ALLOWED_IONS.
  ratios : bool, optional
      If False, instead of calculating ratios, just return a vector of the
      wavelength, f', and f''.
  anom_peak : bool, optional
      Whether to use the actual height of the anomalous map instead of the
      calculated f'' values.

  Returns
  -------
  numpy.array of float
      A vector containing quantitative properties for classification.
  """

  if elements is None:
    elements = [i for i in ALLOWED_IONS if i not in WATER_RES_NAMES]

  if scatter_env.fpp is None or scatter_env.wavelength is None:
    if ratios:
      return np.zeros(len(elements))
    else:
      return np.zeros(1)

  if anom_peak:
    height = scatter_env.anom_density[0]
  else:
    height = scatter_env.fpp

  if ratios:
    ret = np.fromiter((
      height / sasaki.table(element).at_angstrom(scatter_env.wavelength).fdp()
      for element in elements), float)
  else:
    ret = _flatten_list([height,])
  return ret
Exemple #9
0
def exercise():
  t = sasaki.table("SI")
  assert t.label() == "Si"
  assert t.atomic_number() == 14
  f = t.at_angstrom(2)
  assert f.is_valid_fp()
  assert f.is_valid_fdp()
  assert f.is_valid()
  from cctbx import factor_kev_angstrom
  assert approx_equal(f.fp(), t.at_kev(factor_kev_angstrom / 2).fp())
  assert approx_equal(f.fdp(), t.at_kev(factor_kev_angstrom / 2).fdp())
  assert approx_equal(f.fp(), t.at_ev(1000 * factor_kev_angstrom / 2).fp())
  assert approx_equal(f.fdp(), t.at_ev(1000 * factor_kev_angstrom / 2).fdp())
  c = f.as_complex()
  assert c.real == f.fp()
  assert c.imag == f.fdp()
  verify(t, 0.1, -0.0226, 0.0010) # wide first
  verify(t, 2.89, 0.3824, 1.0517) # wide last
  verify(t, 6.7289, -6.9495, 4.1042) # K edge
  t = sasaki.table("ag")
  assert t.label() == "Ag"
  assert t.atomic_number() == 47
  verify(t, 3.2426, -8.6870, 14.1062) # L1 edge
  verify(t, 3.5169, -16.5123, 13.7723) # L2 edge
  verify(t, 3.6995, -29.9836, 10.5137) # L3 edge, right before edge
  verify(t, 3.6996, -32.2967, 3.1759) # L3 edge, right after edge
  n = 0
  for t in sasaki.table_iterator():
    n += 1
    if (n == 1):
      assert t.label() == "Li"
    elif (n == 82):
      assert t.label() == "U"
    u = sasaki.table(t.label())
    assert u.label() == t.label()
  assert n == 82
 def show_plot (self,
     elements,
     range_type="wavelength",
     range=(0.75,2.5),
     n_points=100,
     include_fp=True,
     table="sasaki") :
   assert (range_type in ["wavelength", "energy"])
   assert (table in ["sasaki", "henke"])
   assert (n_points >= 10)
   x_min, x_max = range
   assert (x_max > x_min)
   if (range_type == "wavelength") :
     x_label = "Wavelength (Angstroms)"
   else :
     x_label= "Energy (eV)"
   table_module = None
   if (table == "sasaki") :
     from cctbx.eltbx import sasaki as table_module
   elif (table == "henke") :
     from cctbx.eltbx import henke as table_module
   assert (table_module is not None)
   increment = (x_max - x_min) / n_points
   x_points = [ x_min + increment*x for x in xrange(n_points+1) ]
   self.figure.clear()
   ax = self.figure.add_subplot(111)
   labels = []
   for element in elements :
     try :
       scatt_table = table_module.table(element.upper())
     except ValueError, e :
       raise Sorry(str(e))
     fp = []
     fdp = []
     for x in x_points :
       if (range_type == "wavelength") :
         scatt = scatt_table.at_angstrom(x)
       else :
         scatt = scatt_table.at_ev(x)
       fp.append(scatt.fp())
       fdp.append(scatt.fdp())
     fdp_line = ax.plot(x_points, fdp)[0]
     ax.plot(x_points, fp, linestyle='--', color=fdp_line.get_color())
     labels.append("%s f''" % scatt_table.label())
     labels.append("%s f'" % scatt_table.label())
Exemple #11
0
def show_scatterers(self,fpp,wave):
    print ("""Label            f"      Coordinates        Occupancy """
                 "Uiso, Ustar as Uiso")
    scatterers = self.scatterers()
    types_used = {}
    for j,sc in enumerate(scatterers):
      sc.fdp = fpp[j]
      show_scatterer(sc, unit_cell=self.unit_cell())
      types_used[sc.scattering_type]=None
    print "Tabular values for %7.1f eV (%8.5f Angstrom):"%(12398/wave,wave)
    from cctbx.eltbx import sasaki, henke
    for tag in types_used.keys():
      fpp_expected_sasaki = sasaki.table(tag).at_angstrom(
          wave).fdp()
      fpp_expected_henke = henke.table(tag).at_angstrom(
          wave).fdp()
      print "           %-4s"%tag,
      print "%6.3f" % (max(fpp_expected_sasaki,fpp_expected_henke))
def find_anomalous_scatterer_groups (
    pdb_atoms,
    xray_structure,
    group_same_element=True, # XXX should this be True by default?
    out=None) :
  """
  Automatic setup of anomalously scattering atoms, defined here as anything
  with atomic number 15 (P) or greater.  Not yet accessible from phenix.refine.
  """
  from cctbx.eltbx import sasaki
  from cctbx import xray
  if (out is None) : out = sys.stdout
  element_i_seqs = {}
  groups = []
  if (out is None) : out = null_out()
  hd_selection = xray_structure.hd_selection()
  for i_seq, scatterer in enumerate(xray_structure.scatterers()) :
    if (hd_selection[i_seq]) :
      continue
    element = scatterer.element_symbol().strip()
    try :
      atomic_number = sasaki.table(element).atomic_number()
    except RuntimeError, e :
      print >> out, "Error for %s" % pdb_atoms[i_seq].id_str()
      print >> out, "  " + str(e)
      continue
    if (atomic_number >= 15) :
      if (group_same_element) :
        if (not element in element_i_seqs) :
          element_i_seqs[element] = flex.size_t()
        element_i_seqs[element].append(i_seq)
      else :
        print >> out, "  creating anomalous group for %s" % \
          pdb_atoms[i_seq].id_str()
        asg = xray.anomalous_scatterer_group(
          iselection=flex.size_t([i_seq]),
          f_prime=0,
          f_double_prime=0,
          refine=["f_prime","f_double_prime"],
          selection_string=get_single_atom_selection_string(pdb_atoms[i_seq]))
        groups.append(asg)
Exemple #13
0
def sort_atoms_permutation(pdb_atoms, xray_structure):
    """
  Creates a list of atoms in pdb_atoms, sorted first by their atomic number,
  then by occupancy, and finally, by isotropic b-factor.

  Parameters
  ----------
  pdb_atoms : iotbx.pdb.hierarchy.af_shared_atom
  xray_structure : cctbx.xray.structure.structure

  Returns
  -------
  flex.size_t of int
      i_seqs of sorted atoms
  """
    assert pdb_atoms.size() == xray_structure.scatterers().size()
    pdb_atoms.reset_i_seq()
    atoms_sorted = sorted(
        pdb_atoms, key=lambda x: (sasaki.table(x.element.strip().upper()).atomic_number(), x.occ, x.b), reverse=True
    )
    sele = flex.size_t([atom.i_seq for atom in atoms_sorted])
    return sele
Exemple #14
0
def get_fp_fdp(atom_type=None,wavelength=None,out=sys.stdout):
  if not atom_type or not wavelength:
    raise Sorry("Please specify either f_double_prime or " +
      "atom_type and wavelength")
  from cctbx.eltbx import sasaki
  try:
    table = sasaki.table(atom_type)
    fp_fdp = table.at_angstrom(wavelength)
  except Exception:
    return None
#
  if not fp_fdp.is_valid():
    from cctbx.eltbx import henke
    try:
      table = henke.table(atom_type)
      fp_fdp = table.at_angstrom(wavelength)
    except Exception:
      return None
    #print "Using Henke tables for scattering factors"
  if fp_fdp.is_valid():
    return fp_fdp
  else:
    return None
def find_and_build_ions (
      manager,
      fmodels,
      model,
      wavelength,
      params,
      nproc=1,
      elements=Auto,
      out=None,
      run_ordered_solvent=False,
      occupancy_strategy_enabled=False,
      group_anomalous_strategy_enabled=False,
      use_svm=None) :
  """
  Analyzes the water molecules in a structure and re-labels them as ions if
  they scatter and bind environments that we expect of that ion.

  Parameters
  ----------
  manager : mmtbx.ions.identity.manager
  fmodels : mmtbx.fmodels
  model : mmtbx.model.manager
  wavelength : float
  params : libtbx.phil.scope_extract
  nproc : int, optional
  elements : list of str, optional
  out : file, optional
  run_ordered_solvent : bool, optional
  occupancy_strategy_enabled : bool, optional
  group_anomalous_strategy_enabled : bool, optional
  use_svm : bool, optional

  See Also
  --------
  mmtbx.ions.identify.manager.analyze_waters
  """
  import mmtbx.refinement.minimization
  from mmtbx.refinement.anomalous_scatterer_groups import \
    get_single_atom_selection_string
  from mmtbx.refinement import anomalous_scatterer_groups
  import mmtbx.ions.identify
  import mmtbx.ions.svm
  from cctbx.eltbx import sasaki
  from cctbx import crystal
  from cctbx import adptbx
  from cctbx import xray
  from scitbx.array_family import flex
  import scitbx.lbfgs
  if (use_svm is None) :
    use_svm = getattr(params, "use_svm", False)
  assert (1.0 >= params.initial_occupancy >= 0)
  fmodel = fmodels.fmodel_xray()
  anomalous_flag = fmodel.f_obs().anomalous_flag()
  if (out is None) : out = sys.stdout
  model.xray_structure = fmodel.xray_structure
  model.xray_structure.tidy_us()
  pdb_hierarchy = model.pdb_hierarchy(sync_with_xray_structure=True)
  pdb_atoms = pdb_hierarchy.atoms()
  pdb_atoms.reset_i_seq()
  # FIXME why does B for anisotropic waters end up negative?
  u_iso = model.xray_structure.extract_u_iso_or_u_equiv()
  for i_seq, atom in enumerate(pdb_atoms) :
    labels = atom.fetch_labels()
    if (labels.resname == "HOH") and (atom.b < 0) :
      assert (u_iso[i_seq] >= 0)
      atom.b = adptbx.u_as_b(u_iso[i_seq])
  if (manager is None) :
    manager_class = None
    if (use_svm) :
      manager_class = mmtbx.ions.svm.manager
      if params.svm.svm_name == "merged_high_res" :
        params.find_anomalous_substructure = False
        params.use_phaser = False
    manager = mmtbx.ions.identify.create_manager(
      pdb_hierarchy=pdb_hierarchy,
      geometry_restraints_manager=model.restraints_manager.geometry,
      fmodel=fmodel,
      wavelength=wavelength,
      params=params,
      nproc=nproc,
      verbose=params.debug,
      log=out,
      manager_class=manager_class)
  else :
    grm = model.restraints_manager.geometry
    connectivity = grm.shell_sym_tables[0].full_simple_connectivity()
    manager.update_structure(
      pdb_hierarchy=pdb_hierarchy,
      xray_structure=fmodel.xray_structure,
      connectivity=connectivity,
      log=out)
    manager.update_maps()
  model.update_anomalous_groups(out=out)
  make_sub_header("Analyzing water molecules", out=out)
  manager.show_current_scattering_statistics(out=out)
  anomalous_groups = []
  # XXX somehow comma-separation of phil strings fields doesn't work
  if (isinstance(elements, list)) and (len(elements) == 1) :
    elements = elements[0].split(",")
  water_ion_candidates = manager.analyze_waters(
    out=out,
    candidates=elements)
  modified_iselection = flex.size_t()
  default_b_iso = manager.get_initial_b_iso()
  # Build in the identified ions
  for_building = []
  if (use_svm) :
    for result in water_ion_candidates :
      for_building.append((result.i_seq, result.final_choice))
  else :
    for i_seq, final_choices, two_fofc in water_ion_candidates :
      if (len(final_choices) == 1) :
        for_building.append((i_seq, final_choices[0]))
  skipped = []
  if (len(for_building) > 0) :
    make_sub_header("Adding %d ions to model" % len(for_building), out)
    for k, (i_seq, final_choice) in enumerate(for_building) :
      atom = manager.pdb_atoms[i_seq]
      skip = False
      for other_i_seq, other_ion in for_building[:k] :
        if (other_i_seq in skipped) : continue
        if (((other_ion.charge > 0) and (final_choice.charge > 0)) or
            ((other_ion.charge < 0) and (final_choice.charge < 0))) :
          other_atom = manager.pdb_atoms[other_i_seq]
          dxyz = atom.distance(other_atom)
          if (dxyz < params.max_distance_between_like_charges) :
            print >> out, \
              "  %s (%s%+d) is only %.3fA from %s (%s%+d), skipping for now" %\
              (atom.id_str(), final_choice.element, final_choice.charge, dxyz,
               other_atom.id_str(), other_ion.element, other_ion.charge)
            skipped.append(i_seq)
            skip = True
            break
      if (skip) : continue
      print >> out, "  %s becomes %s%+d" % \
          (atom.id_str(), final_choice.element, final_choice.charge)
      refine_adp = params.refine_ion_adp
      if (refine_adp == "Auto") :
        if (fmodel.f_obs().d_min() <= 1.5) :
          refine_adp = "anisotropic"
        elif (fmodel.f_obs().d_min() < 2.5) :
          atomic_number = sasaki.table(final_choice.element).atomic_number()
          if (atomic_number >= 19) :
            refine_adp = "anisotropic"
      # Modify the atom object - this is clumsy but they will be grouped into
      # a single chain at the end of refinement
      initial_b_iso = params.initial_b_iso
      if (initial_b_iso is Auto) :
        initial_b_iso = manager.guess_b_iso_real(i_seq)
      element = final_choice.element
      if (element == "IOD") : # FIXME
        element = "I"
      modified_atom = model.convert_atom(
        i_seq=i_seq,
        scattering_type=final_choice.scattering_type(),
        atom_name=element,
        element=element,
        charge=final_choice.charge,
        residue_name=final_choice.element,
        initial_occupancy=params.initial_occupancy,
        initial_b_iso=initial_b_iso,
        chain_id=params.ion_chain_id,
        segid="ION",
        refine_adp=refine_adp,
        refine_occupancies=False) #params.refine_ion_occupancies)
      if (params.refine_anomalous) and (anomalous_flag) :
        scatterer = model.xray_structure.scatterers()[i_seq]
        if (wavelength is not None) :
          fp_fdp_info = sasaki.table(final_choice.element).at_angstrom(
            wavelength)
          scatterer.fp = fp_fdp_info.fp()
          scatterer.fdp = fp_fdp_info.fdp()
          print >> out, "    setting f'=%g, f''=%g" % (scatterer.fp,
            scatterer.fdp)
        group = xray.anomalous_scatterer_group(
          iselection=flex.size_t([i_seq]),
          f_prime=scatterer.fp,
          f_double_prime=scatterer.fdp,
          refine=["f_prime","f_double_prime"],
          selection_string=get_single_atom_selection_string(modified_atom),
          update_from_selection=True)
        anomalous_groups.append(group)
      modified_iselection.append(i_seq)
  if (len(modified_iselection) > 0) :
    scatterers = model.xray_structure.scatterers()
    # FIXME not sure this is actually working as desired...
    site_symmetry_table = model.xray_structure.site_symmetry_table()
    for i_seq in site_symmetry_table.special_position_indices() :
      scatterers[i_seq].site = crystal.correct_special_position(
        crystal_symmetry=model.xray_structure,
        special_op=site_symmetry_table.get(i_seq).special_op(),
        site_frac=scatterers[i_seq].site,
        site_label=scatterers[i_seq].label,
        tolerance=1.0)
    model.xray_structure.replace_scatterers(scatterers=scatterers)
    def show_r_factors () :
       return "r_work=%6.4f r_free=%6.4f" % (fmodel.r_work(), fmodel.r_free())
    fmodel.update_xray_structure(
      xray_structure=model.xray_structure,
      update_f_calc=True,
      update_f_mask=True)
    n_anom = len(anomalous_groups)
    refine_anomalous = anomalous_flag and params.refine_anomalous and n_anom>0
    refine_occupancies = ((params.refine_ion_occupancies or refine_anomalous)
      and ((not occupancy_strategy_enabled) or
           (model.refinement_flags.s_occupancies is None) or
           (len(model.refinement_flags.s_occupancies) == 0)))
    if (refine_anomalous) :
      if ((model.anomalous_scatterer_groups is not None) and
          (group_anomalous_strategy_enabled)) :
        model.anomalous_scatterer_groups.extend(anomalous_groups)
        refine_anomalous = False
    if (refine_occupancies) or (refine_anomalous) :
      print >> out, ""
      print >> out, "  occupancy refinement (new ions only): start %s" % \
        show_r_factors()
      fmodel.xray_structure.scatterers().flags_set_grads(state = False)
      fmodel.xray_structure.scatterers().flags_set_grad_occupancy(
        iselection = modified_iselection)
      lbfgs_termination_params = scitbx.lbfgs.termination_parameters(
        max_iterations = 25)
      minimized = mmtbx.refinement.minimization.lbfgs(
        restraints_manager       = None,
        fmodels                  = fmodels,
        model                    = model,
        is_neutron_scat_table    = False,
        lbfgs_termination_params = lbfgs_termination_params)
      fmodel.xray_structure.adjust_occupancy(
        occ_max   = 1.0,
        occ_min   = 0,
        selection = modified_iselection)
      zero_occ = []
      for i_seq in modified_iselection :
        occ = fmodel.xray_structure.scatterers()[i_seq].occupancy
        if (occ == 0) :
          zero_occ.append(i_seq)
      fmodel.update_xray_structure(
        update_f_calc=True,
        update_f_mask=True)
      print >> out, "                                        final %s" % \
        show_r_factors()
      if (len(zero_occ) > 0) :
        print >> out, "  WARNING: occupancy dropped to zero for %d atoms:"
        atoms = model.pdb_hierarchy().atoms()
        for i_seq in zero_occ :
          print >> out, "    %s" % atoms[i_seq].id_str(suppress_segid=True)
      print >> out, ""
    if (refine_anomalous) :
      assert fmodel.f_obs().anomalous_flag()
      print >> out, "  anomalous refinement (new ions only): start %s" % \
        show_r_factors()
      fmodel.update(target_name="ls")
      anomalous_scatterer_groups.minimizer(
        fmodel=fmodel,
        groups=anomalous_groups)
      fmodel.update(target_name="ml")
      print >> out, "                                        final %s" % \
        show_r_factors()
      print >> out, ""
  return manager
Exemple #16
0
def find_and_build_ions(manager,
                        fmodels,
                        model,
                        wavelength,
                        params,
                        nproc=1,
                        elements=Auto,
                        out=None,
                        run_ordered_solvent=False,
                        occupancy_strategy_enabled=False,
                        group_anomalous_strategy_enabled=False,
                        use_svm=None):
    """
  Analyzes the water molecules in a structure and re-labels them as ions if
  they scatter and bind environments that we expect of that ion.

  Parameters
  ----------
  manager : mmtbx.ions.identity.manager
  fmodels : mmtbx.fmodels
  model : mmtbx.model.manager
  wavelength : float
  params : libtbx.phil.scope_extract
  nproc : int, optional
  elements : list of str, optional
  out : file, optional
  run_ordered_solvent : bool, optional
  occupancy_strategy_enabled : bool, optional
  group_anomalous_strategy_enabled : bool, optional
  use_svm : bool, optional

  See Also
  --------
  mmtbx.ions.identify.manager.analyze_waters
  """
    import mmtbx.refinement.minimization
    from mmtbx.refinement.anomalous_scatterer_groups import \
      get_single_atom_selection_string
    from mmtbx.refinement import anomalous_scatterer_groups
    import mmtbx.ions.identify
    import mmtbx.ions.svm
    from cctbx.eltbx import sasaki
    from cctbx import crystal
    from cctbx import adptbx
    from cctbx import xray
    from scitbx.array_family import flex
    import scitbx.lbfgs
    if (use_svm is None):
        use_svm = getattr(params, "use_svm", False)
    assert (1.0 >= params.initial_occupancy >= 0)
    fmodel = fmodels.fmodel_xray()
    anomalous_flag = fmodel.f_obs().anomalous_flag()
    if (out is None): out = sys.stdout
    model.set_xray_structure(fmodel.xray_structure)
    model.get_xray_structure().tidy_us()
    pdb_hierarchy = model.get_hierarchy()
    pdb_atoms = pdb_hierarchy.atoms()
    pdb_atoms.reset_i_seq()
    # FIXME why does B for anisotropic waters end up negative?
    u_iso = model.get_xray_structure().extract_u_iso_or_u_equiv()
    for i_seq, atom in enumerate(pdb_atoms):
        labels = atom.fetch_labels()
        if (labels.resname == "HOH") and (atom.b < 0):
            assert (u_iso[i_seq] >= 0)
            atom.b = adptbx.u_as_b(u_iso[i_seq])
    if (manager is None):
        manager_class = None
        if (use_svm):
            manager_class = mmtbx.ions.svm.manager
            if params.svm.svm_name == "merged_high_res":
                params.find_anomalous_substructure = False
                params.use_phaser = False
        manager = mmtbx.ions.identify.create_manager(
            pdb_hierarchy=pdb_hierarchy,
            geometry_restraints_manager=model.restraints_manager.geometry,
            fmodel=fmodel,
            wavelength=wavelength,
            params=params,
            nproc=nproc,
            verbose=params.debug,
            log=out,
            manager_class=manager_class)
    else:
        grm = model.get_restraints_manager().geometry
        connectivity = grm.shell_sym_tables[0].full_simple_connectivity()
        manager.update_structure(pdb_hierarchy=pdb_hierarchy,
                                 xray_structure=fmodel.xray_structure,
                                 connectivity=connectivity,
                                 log=out)
        manager.update_maps()
    model.update_anomalous_groups(out=out)
    make_sub_header("Analyzing water molecules", out=out)
    manager.show_current_scattering_statistics(out=out)
    anomalous_groups = []
    # XXX somehow comma-separation of phil strings fields doesn't work
    if (isinstance(elements, list)) and (len(elements) == 1):
        elements = elements[0].split(",")
    water_ion_candidates = manager.analyze_waters(out=out, candidates=elements)
    modified_iselection = flex.size_t()
    default_b_iso = manager.get_initial_b_iso()
    # Build in the identified ions
    for_building = []
    if (use_svm):
        for result in water_ion_candidates:
            for_building.append((result.i_seq, result.final_choice))
    else:
        for i_seq, final_choices, two_fofc in water_ion_candidates:
            if (len(final_choices) == 1):
                for_building.append((i_seq, final_choices[0]))
    skipped = []
    if (len(for_building) > 0):
        make_sub_header("Adding %d ions to model" % len(for_building), out)
        for k, (i_seq, final_choice) in enumerate(for_building):
            atom = manager.pdb_atoms[i_seq]
            skip = False
            for other_i_seq, other_ion in for_building[:k]:
                if (other_i_seq in skipped): continue
                if (((other_ion.charge > 0) and (final_choice.charge > 0)) or
                    ((other_ion.charge < 0) and (final_choice.charge < 0))):
                    other_atom = manager.pdb_atoms[other_i_seq]
                    dxyz = atom.distance(other_atom)
                    if (dxyz < params.max_distance_between_like_charges):
                        print("  %s (%s%+d) is only %.3fA from %s (%s%+d), skipping for now" %\
                          (atom.id_str(), final_choice.element, final_choice.charge, dxyz,
                           other_atom.id_str(), other_ion.element, other_ion.charge), file=out)
                        skipped.append(i_seq)
                        skip = True
                        break
            if (skip): continue
            print("  %s becomes %s%+d" % \
                (atom.id_str(), final_choice.element, final_choice.charge), file=out)
            refine_adp = params.refine_ion_adp
            if (refine_adp == "Auto"):
                if (fmodel.f_obs().d_min() <= 1.5):
                    refine_adp = "anisotropic"
                elif (fmodel.f_obs().d_min() < 2.5):
                    atomic_number = sasaki.table(
                        final_choice.element).atomic_number()
                    if (atomic_number >= 19):
                        refine_adp = "anisotropic"
            # Modify the atom object - this is clumsy but they will be grouped into
            # a single chain at the end of refinement
            initial_b_iso = params.initial_b_iso
            if (initial_b_iso is Auto):
                initial_b_iso = manager.guess_b_iso_real(i_seq)
            element = final_choice.element
            if (element == "IOD"):  # FIXME
                element = "I"
            modified_atom = model.convert_atom(
                i_seq=i_seq,
                scattering_type=final_choice.scattering_type(),
                atom_name=element,
                element=element,
                charge=final_choice.charge,
                residue_name=final_choice.element,
                initial_occupancy=params.initial_occupancy,
                initial_b_iso=initial_b_iso,
                chain_id=params.ion_chain_id,
                segid="ION",
                refine_adp=refine_adp,
                refine_occupancies=False)  #params.refine_ion_occupancies)
            if (params.refine_anomalous) and (anomalous_flag):
                scatterer = model.get_xray_structure().scatterers()[i_seq]
                if (wavelength is not None):
                    fp_fdp_info = sasaki.table(
                        final_choice.element).at_angstrom(wavelength)
                    scatterer.fp = fp_fdp_info.fp()
                    scatterer.fdp = fp_fdp_info.fdp()
                    print("    setting f'=%g, f''=%g" %
                          (scatterer.fp, scatterer.fdp),
                          file=out)
                group = xray.anomalous_scatterer_group(
                    iselection=flex.size_t([i_seq]),
                    f_prime=scatterer.fp,
                    f_double_prime=scatterer.fdp,
                    refine=["f_prime", "f_double_prime"],
                    selection_string=get_single_atom_selection_string(
                        modified_atom),
                    update_from_selection=True)
                anomalous_groups.append(group)
            modified_iselection.append(i_seq)
    if (len(modified_iselection) > 0):
        scatterers = model.get_xray_structure().scatterers()
        # FIXME not sure this is actually working as desired...
        site_symmetry_table = model.get_xray_structure().site_symmetry_table()
        for i_seq in site_symmetry_table.special_position_indices():
            scatterers[i_seq].site = crystal.correct_special_position(
                crystal_symmetry=model.get_xray_structure(),
                special_op=site_symmetry_table.get(i_seq).special_op(),
                site_frac=scatterers[i_seq].site,
                site_label=scatterers[i_seq].label,
                tolerance=1.0)
        model.get_xray_structure().replace_scatterers(scatterers=scatterers)
        model.set_xray_structure(model.get_xray_structure())

        def show_r_factors():
            return "r_work=%6.4f r_free=%6.4f" % (fmodel.r_work(),
                                                  fmodel.r_free())

        fmodel.update_xray_structure(xray_structure=model.get_xray_structure(),
                                     update_f_calc=True,
                                     update_f_mask=True)
        n_anom = len(anomalous_groups)
        refine_anomalous = anomalous_flag and params.refine_anomalous and n_anom > 0
        refine_occupancies = (
            (params.refine_ion_occupancies or refine_anomalous)
            and ((not occupancy_strategy_enabled) or
                 (model.refinement_flags.s_occupancies is None) or
                 (len(model.refinement_flags.s_occupancies) == 0)))
        if (refine_anomalous):
            if (model.have_anomalous_scatterer_groups()
                    and (group_anomalous_strategy_enabled)):
                model.set_anomalous_scatterer_groups(
                    model.get_anomalous_scatterer_groups() + anomalous_groups)
                refine_anomalous = False
        if (refine_occupancies) or (refine_anomalous):
            print("", file=out)
            print("  occupancy refinement (new ions only): start %s" % \
              show_r_factors(), file=out)
            fmodel.xray_structure.scatterers().flags_set_grads(state=False)
            fmodel.xray_structure.scatterers().flags_set_grad_occupancy(
                iselection=modified_iselection)
            lbfgs_termination_params = scitbx.lbfgs.termination_parameters(
                max_iterations=25)
            minimized = mmtbx.refinement.minimization.lbfgs(
                restraints_manager=None,
                fmodels=fmodels,
                model=model,
                is_neutron_scat_table=False,
                lbfgs_termination_params=lbfgs_termination_params)
            fmodel.xray_structure.adjust_occupancy(
                occ_max=1.0, occ_min=0, selection=modified_iselection)
            zero_occ = []
            for i_seq in modified_iselection:
                occ = fmodel.xray_structure.scatterers()[i_seq].occupancy
                if (occ == 0):
                    zero_occ.append(i_seq)
            fmodel.update_xray_structure(update_f_calc=True,
                                         update_f_mask=True)
            print("                                        final %s" % \
              show_r_factors(), file=out)
            if (len(zero_occ) > 0):
                print("  WARNING: occupancy dropped to zero for %d atoms:",
                      file=out)
                atoms = model.get_atoms()
                for i_seq in zero_occ:
                    print("    %s" % atoms[i_seq].id_str(suppress_segid=True),
                          file=out)
            print("", file=out)
        if (refine_anomalous):
            assert fmodel.f_obs().anomalous_flag()
            print("  anomalous refinement (new ions only): start %s" % \
              show_r_factors(), file=out)
            fmodel.update(target_name="ls")
            anomalous_scatterer_groups.minimizer(fmodel=fmodel,
                                                 groups=anomalous_groups)
            fmodel.update(target_name="ml")
            print("                                        final %s" % \
              show_r_factors(), file=out)
            print("", file=out)
    return manager
def examples():
    # Generate space groups (in matrix/vector form) based on spacegroup number
    # (names are *not* a pain)
    # See also: http://cctbx.sourceforge.net/current/c_plus_plus/classcctbx_1_1sgtbx_1_1space__group__symbols.html#_details
    from cctbx import sgtbx
    for s in sgtbx.space_group_info(symbol="I41/amd").group():
        print(s)  # in "xyz" notation
        print(s.r().as_rational().mathematica_form(), \
              s.t().as_rational().transpose().mathematica_form())
    print()

    # now with a space group number
    space_group_info = sgtbx.space_group_info(number=123)
    space_group_info.show_summary()
    print()

    # Generate conditions for allowed reflections etc
    from cctbx import crystal
    from cctbx import miller
    crystal_symmetry = crystal.symmetry(unit_cell=(10, 10, 13, 90, 90, 90),
                                        space_group_info=space_group_info)
    miller_set = miller.build_set(crystal_symmetry=crystal_symmetry,
                                  anomalous_flag=False,
                                  d_min=4)
    # change the space group in order to get a few systematic absences
    miller_set = miller_set.customized_copy(
        space_group_info=sgtbx.space_group_info(symbol="I41/amd"))
    sys_absent_flags = miller_set.sys_absent_flags()
    for h, f in zip(sys_absent_flags.indices(), sys_absent_flags.data()):
        print(h, f)
    print()
    # try also (from the command line): libtbx.help cctbx.miller

    # Generate point group of space group in matrix form
    point_group = miller_set.space_group().build_derived_point_group()
    point_group_info = sgtbx.space_group_info(group=point_group)
    point_group_info.show_summary()
    for s in point_group:
        print(s)
    print()

    # Generate point-group matrices for given coordinate
    # first we have to define what we consider as special position
    special_position_settings = crystal.special_position_settings(
        crystal_symmetry=miller_set, min_distance_sym_equiv=0.5)  # <<<<< here
    site_symmetry = special_position_settings.site_symmetry(site=(0, 0.48, 0))
    print("special position operator:", site_symmetry.special_op_simplified())
    print("distance to original site:", site_symmetry.distance_moved())
    print("point group of the special position:")
    for s in site_symmetry.matrices():
        print(s)
    print()
    # See also: http://cci.lbl.gov/~rwgk/my_papers/iucr/au0265_reprint.pdf

    # Access database for form factors
    from cctbx.eltbx import xray_scattering
    si_form_factor = xray_scattering.it1992("Si")
    gaussians = si_form_factor.fetch()
    for stol in [0, 0.01, 0.02, 0.5]:
        print(stol, gaussians.at_stol(stol))
    print()

    # anomalous scattering factors: Sasaki tables
    from cctbx.eltbx import sasaki
    si_table = sasaki.table("Si")
    for wavelength in [0.5, 0.8, 0.9]:
        data = si_table.at_angstrom(wavelength)
        print(wavelength, data.fp(), data.fdp())
    print()

    # anomalous scattering factors: Henke tables
    from cctbx.eltbx import henke
    si_table = henke.table("Si")
    for wavelength in [0.5, 0.8, 0.9]:
        data = si_table.at_angstrom(wavelength)
        print(wavelength, data.fp(), data.fdp())
    print()
    print("OK")
def examples():
  # Generate space groups (in matrix/vector form) based on spacegroup number
  # (names are *not* a pain)
  # See also: http://cctbx.sourceforge.net/current/c_plus_plus/classcctbx_1_1sgtbx_1_1space__group__symbols.html#_details
  from cctbx import sgtbx
  for s in sgtbx.space_group_info(symbol="I41/amd").group():
    print s # in "xyz" notation
    print s.r().as_rational().mathematica_form(), \
          s.t().as_rational().transpose().mathematica_form()
  print

  # now with a space group number
  space_group_info = sgtbx.space_group_info(number=123)
  space_group_info.show_summary()
  print

  # Generate conditions for allowed reflections etc
  from cctbx import crystal
  from cctbx import miller
  crystal_symmetry = crystal.symmetry(
    unit_cell=(10,10,13,90,90,90),
    space_group_info=space_group_info)
  miller_set = miller.build_set(
    crystal_symmetry=crystal_symmetry,
    anomalous_flag=False,
    d_min=4)
  # change the space group in order to get a few systematic absences
  miller_set = miller_set.customized_copy(
    space_group_info=sgtbx.space_group_info(symbol="I41/amd"))
  sys_absent_flags = miller_set.sys_absent_flags()
  for h,f in zip(sys_absent_flags.indices(), sys_absent_flags.data()):
    print h, f
  print
  # try also (from the command line): libtbx.help cctbx.miller

  # Generate point group of space group in matrix form
  point_group = miller_set.space_group().build_derived_point_group()
  point_group_info = sgtbx.space_group_info(group=point_group)
  point_group_info.show_summary()
  for s in point_group:
    print s
  print

  # Generate point-group matrices for given coordinate
  # first we have to define what we consider as special position
  special_position_settings = crystal.special_position_settings(
    crystal_symmetry=miller_set,
    min_distance_sym_equiv=0.5) # <<<<< here
  site_symmetry = special_position_settings.site_symmetry(
    site=(0,0.48,0))
  print "special position operator:", site_symmetry.special_op_simplified()
  print "distance to original site:", site_symmetry.distance_moved()
  print "point group of the special position:"
  for s in site_symmetry.matrices():
    print s
  print
  # See also: http://cci.lbl.gov/~rwgk/my_papers/iucr/au0265_reprint.pdf

  # Access database for form factors
  from cctbx.eltbx import xray_scattering
  si_form_factor = xray_scattering.it1992("Si")
  gaussians = si_form_factor.fetch()
  for stol in [0, 0.01, 0.02, 0.5]:
    print stol, gaussians.at_stol(stol)
  print

  # anomalous scattering factors: Sasaki tables
  from cctbx.eltbx import sasaki
  si_table = sasaki.table("Si")
  for wavelength in [0.5, 0.8, 0.9]:
    data = si_table.at_angstrom(wavelength)
    print wavelength, data.fp(), data.fdp()
  print

  # anomalous scattering factors: Henke tables
  from cctbx.eltbx import henke
  si_table = henke.table("Si")
  for wavelength in [0.5, 0.8, 0.9]:
    data = si_table.at_angstrom(wavelength)
    print wavelength, data.fp(), data.fdp()
  print
  print "OK"