Exemplo n.º 1
0
    def _ksol_bsol_grid_search(self):
        # XXX HERE
        start_r_factor = self.fmodel_kbu.r_factor()
        final_ksol = self.fmodel_kbu.data.k_sols()
        final_bsol = self.fmodel_kbu.data.b_sols()
        final_b_cart = self.fmodel_kbu.b_cart()
        final_r_factor = start_r_factor

        k_sols = kb_range(0.6, 0.0, 0.1)
        b_sols = kb_range(80., 10, 5)
        assert len(self.fmodel_kbu.f_masks) == 1
        o = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
            f_obs=self.fmodel_kbu.f_obs.data(),
            f_calc=self.fmodel_kbu.f_calc.data(),
            f_mask=self.fmodel_kbu.f_masks[0].data(),
            ss=self.fmodel_kbu.ss,
            k_sol_range=flex.double(k_sols),
            b_sol_range=flex.double(b_sols),
            miller_indices=self.fmodel_kbu.f_obs.indices(),
            r_ref=start_r_factor)
        if (o.updated()):
            assert o.r() < start_r_factor
            final_r_factor = o.r()
            final_ksol = o.k_sol()
            final_bsol = o.b_sol()
            final_b_cart = adptbx.u_as_b(
                adptbx.u_star_as_u_cart(self.fmodel_kbu.f_obs.unit_cell(),
                                        o.u_star()))
            self.fmodel_kbu.update(k_sols=[final_ksol],
                                   b_sols=[final_bsol],
                                   b_cart=final_b_cart)
            assert self.fmodel_kbu.r_factor() <= start_r_factor
            if (final_ksol < 0.01):
                final_ksol = 0
                self.fmodel_kbu.update(k_sols=[final_ksol])
                final_r_factor = self.fmodel_kbu.r_factor()
            else:
                o = k_sol_b_sol_b_cart_minimizer(fmodel_kbu=self.fmodel_kbu,
                                                 refine_kbu=True)
                if (o.kbu.r_factor() < final_r_factor):
                    final_b_cart = adptbx.u_as_b(
                        adptbx.u_star_as_u_cart(
                            self.fmodel_kbu.f_obs.unit_cell(), o.kbu.u_star()))
                    final_ksol = list(o.kbu.k_sols())
                    final_bsol = list(o.kbu.b_sols())
                    self.fmodel_kbu.update(k_sols=final_ksol,
                                           b_sols=final_bsol,
                                           b_cart=final_b_cart)
                else:
                    self.fmodel_kbu.update(k_sols=[final_ksol],
                                           b_sols=[final_bsol],
                                           b_cart=final_b_cart)
                final_r_factor = self.fmodel_kbu.r_factor()
                assert self.fmodel_kbu.r_factor() <= start_r_factor
        self.fmodel_kbu.update(k_sols=final_ksol,
                               b_sols=final_bsol,
                               b_cart=final_b_cart)
        assert abs(self.fmodel_kbu.r_factor() - final_r_factor) < 1.e-6
        assert self.fmodel_kbu.r_factor() <= start_r_factor
        return final_ksol, final_bsol, final_b_cart, final_r_factor
  def update_solvent_and_scale_twin(self, refine_hd_scattering, log):
    if(not self.twinned()): return
    assert len(self.f_masks()) == 1
    # Re-set all scales to unit or zero
    self.show(prefix = "update scales twin start", log = log)
    self.reset_all_scales()
    self.show(prefix = "reset f_part, k_(total,mask)", log = log)
    f_calc_data      = self.f_calc().data()
    f_calc_data_twin = self.f_calc_twin().data()
    # Initial trial set
    sc = 1000.
    ksr = [i/sc for i in range(ifloor(0*sc), iceil(0.6*sc)+1,  int(0.05*sc))]
    bsr = [i/sc for i in range(ifloor(0*sc), iceil(150.*sc)+1, int(10.*sc))]
    o_kbu_sol = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
      f_obs          = self.f_obs().data(),
      f_calc_1       = f_calc_data,
      f_calc_2       = f_calc_data_twin,
      f_mask_1       = self.arrays.core.f_masks[0].data(),
      f_mask_2       = self.arrays.core_twin.f_masks[0].data(),
      ss             = self.ss,
      twin_fraction  = self.twin_fraction,
      k_sol_range    = flex.double(ksr),
      b_sol_range    = flex.double(bsr),
      miller_indices = self.f_obs().indices(), #XXX ??? What about twin-related?
      unit_cell      = self.f_obs().unit_cell(),
      r_ref          = self.r_all())
    if(o_kbu_sol.updated()):
      self.update(
        k_mask        = o_kbu_sol.k_mask(),
        k_anisotropic = o_kbu_sol.k_anisotropic())
    # Second (finer) trial set
    k_min = max(o_kbu_sol.k_sol()-0.05, 0)
    k_max = min(o_kbu_sol.k_sol()+0.05, 0.6)
    ksr = [i/sc for i in range(ifloor(k_min*sc), iceil(k_max*sc)+1, int(0.01*sc))]
    b_min = max(o_kbu_sol.b_sol()-10, 0)
    b_max = min(o_kbu_sol.b_sol()+10, 150)
    bsr = [i/sc for i in range(ifloor(b_min*sc), iceil(b_max*sc)+1, int(1.*sc))]
    o_kbu_sol = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
      f_obs          = self.f_obs().data(),
      f_calc_1       = f_calc_data,
      f_calc_2       = f_calc_data_twin,
      f_mask_1       = self.arrays.core.f_masks[0].data(),
      f_mask_2       = self.arrays.core_twin.f_masks[0].data(),
      ss             = self.ss,
      twin_fraction  = self.twin_fraction,
      k_sol_range    = flex.double(ksr),
      b_sol_range    = flex.double(bsr),
      miller_indices = self.f_obs().indices(), #XXX ??? What about twin-related?
      unit_cell      = self.f_obs().unit_cell(),
      r_ref          = o_kbu_sol.r())
    if(o_kbu_sol.updated()):
      self.update(
        k_mask        = o_kbu_sol.k_mask(),
        k_anisotropic = o_kbu_sol.k_anisotropic())
      assert approx_equal(self.r_all(), o_kbu_sol.r())
      ##############
      # use apply_back_trace in if below
      if(self.xray_structure is not None):
        o = mmtbx.bulk_solvent.scaler.tmp(
          xray_structure = self.xray_structure,
          k_anisotropic  = o_kbu_sol.k_anisotropic(),
          k_masks        = [o_kbu_sol.k_mask()],
          ss             = self.ss)
        self.update_xray_structure(
          xray_structure = o.xray_structure,
          update_f_calc  = True)
      #############
        self.update(
          k_mask        = o.k_masks,
          k_anisotropic = o.k_anisotropic)

    self.show(prefix = "bulk-solvent and scaling", log = log)
    #
    # Add contribution from H (if present and riding). This goes to f_part2.
    #
    kh, bh = 0, 0
    if(refine_hd_scattering and
       self.need_to_refine_hd_scattering_contribution()):
      hd_selection = self.xray_structure.hd_selection()
      xrs_no_h = self.xray_structure.select(~hd_selection)
      xrs_h    = self.xray_structure.select(hd_selection)
      # Accumulate all mask contributions: Fcalc_atoms+Fbulk_1+...+Fbulk_N
      data = self.f_calc().data()+self.f_masks()[0].data()*self.k_masks()[0]
      f_calc_plus_f_bulk_no_scales = self.f_calc().array(data = data)
      data = self.f_calc_twin().data()+\
        self.f_masks_twin()[0].data()*self.k_masks_twin()[0]
      f_calc_plus_f_bulk_no_scales_twin = self.f_calc_twin().array(data = data)
      # Initial FH contribution
      xrs_h = xrs_h.set_occupancies(value=1).set_b_iso(value = 0)
      f_h = self.compute_f_calc(xray_structure = xrs_h)
      f_h_twin = self.compute_f_calc(xray_structure = xrs_h,
        miller_array = self.f_calc_twin())
      # Coarse sampling
      b_mean = flex.mean(xrs_no_h.extract_u_iso_or_u_equiv())*adptbx.u_as_b(1.)
      b_min = int(max(0,b_mean)*0.5)
      b_max = int(b_mean*1.5)
      sc = 1000.
      kr=[i/sc for i in range(ifloor(0*sc), iceil(1.5*sc)+1, int(0.1*sc))]
      br=[i/sc for i in range(ifloor(b_min*sc), iceil(b_max*sc)+1, int(5.*sc))]
      obj = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
        f_obs          = self.f_obs().data(),
        f_calc_1       = f_calc_plus_f_bulk_no_scales.data(),
        f_calc_2       = f_calc_plus_f_bulk_no_scales_twin.data(),
        f_mask_1       = f_h.data(),
        f_mask_2       = f_h_twin.data(),
        ss             = self.ss,
        twin_fraction  = self.twin_fraction,
        k_sol_range    = flex.double(kr),
        b_sol_range    = flex.double(br),
        miller_indices = self.f_obs().indices(), # XXX What about twin-related?
        unit_cell      = self.f_obs().unit_cell(),
        r_ref          = self.r_work())
      if(obj.updated()):
        f_part2      = f_h.array(     data = obj.k_mask()*f_h.data())
        f_part2_twin = f_h_twin.array(data = obj.k_mask()*f_h_twin.data())
        kh, bh = obj.k_sol(), obj.b_sol()
      # Fine sampling
      k_min = max(0,obj.k_sol()-0.1)
      k_max = obj.k_sol()+0.1
      b_min = max(0,obj.b_sol()-5.)
      b_max = obj.b_sol()+5.
      kr=[i/sc for i in range(ifloor(k_min*sc),iceil(k_max*sc)+1,int(0.01*sc))]
      br=[i/sc for i in range(ifloor(b_min*sc),iceil(b_max*sc)+1,int(5.*sc))]
      obj = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
        f_obs          = self.f_obs().data(),
        f_calc_1       = f_calc_plus_f_bulk_no_scales.data(),
        f_calc_2       = f_calc_plus_f_bulk_no_scales_twin.data(),
        f_mask_1       = f_h.data(),
        f_mask_2       = f_h_twin.data(),
        ss             = self.ss,
        twin_fraction  = self.twin_fraction,
        k_sol_range    = flex.double(kr),
        b_sol_range    = flex.double(br),
        miller_indices = self.f_obs().indices(), # XXX What about twin-related?
        unit_cell      = self.f_obs().unit_cell(),
        r_ref          = obj.r())
      if(obj.updated()):
        f_part2      = f_h.array(     data = obj.k_mask()*f_h.data())
        f_part2_twin = f_h_twin.array(data = obj.k_mask()*f_h_twin.data())
        kh, bh = obj.k_sol(), obj.b_sol()
      self.update_core(
        f_part2       = f_part2,
        f_part2_twin  = f_part2_twin,
        k_anisotropic = obj.k_anisotropic())
      self.show(prefix = "add H (%4.2f, %6.2f)"%(kh, bh), log = log)
    b_cart = adptbx.u_as_b(adptbx.u_star_as_u_cart(
                             self.f_obs().unit_cell(), o_kbu_sol.u_star()))
    return group_args(
      k_sol  = o_kbu_sol.k_sol(),
      b_sol  = o_kbu_sol.b_sol(),
      b_cart = b_cart,
      k_h    = kh,
      b_h    = bh)
 def update_solvent_and_scale_2(self, fast, params, apply_back_trace,
                                refine_hd_scattering, log):
   if(params is None): params = bss.master_params.extract()
   if(self.xray_structure is not None):
     # Figure out Fcalc and Fmask based on presence of H
     hd_selection = self.xray_structure.hd_selection()
     xrs_no_h = self.xray_structure.select(~hd_selection)
     xrs_h    = self.xray_structure.select(hd_selection)
   # Create data container for scalers. If H scattering is refined then it is
   # assumed that self.f_calc() does not contain H contribution at all.
   fmodel_kbu = mmtbx.f_model.manager_kbu(
     f_obs   = self.f_obs(),
     f_calc  = self.f_calc(),
     f_masks = self.f_masks(),
     ss      = self.ss)
   # Compute k_total and k_mask using one of the two methods (anal or min).
   # Note: this intentionally ignores previously existing f_part1 and f_part2.
   #
   k_sol, b_sol, b_cart, b_adj = [None,]*4
   if(fast): # analytical
     assert len(fmodel_kbu.f_masks)==1
     result = mmtbx.bulk_solvent.scaler.run_simple(
       fmodel_kbu     = fmodel_kbu,
       r_free_flags   = self.r_free_flags(),
       bulk_solvent   = params.bulk_solvent,
       bin_selections = self.bin_selections)
     r_all_from_scaler = result.r_all() # must be here, before apply_back_trace
   else: # using minimization: exp solvent and scale model (k_sol,b_sol,b_cart)
     result = bss.bulk_solvent_and_scales(
       fmodel_kbu = fmodel_kbu,
       params     = params)
     k_sol, b_sol, b_cart = result.k_sols(), result.b_sols(), result.b_cart()
     r_all_from_scaler = result.r_all() # must be here, before apply_back_trace
   if(apply_back_trace and len(fmodel_kbu.f_masks)==1 and
      self.xray_structure is not None):
     o = result.apply_back_trace_of_overall_exp_scale_matrix(
       xray_structure = self.xray_structure)
     b_adj = o.b_adj
     if(not fast): b_sol, b_cart = [o.b_sol], o.b_cart
     self.update_xray_structure(
       xray_structure = o.xray_structure,
       update_f_calc  = True)
     fmodel_kbu = fmodel_kbu.update(f_calc = self.f_calc())
     self.show(prefix = "overall B=%s to atoms"%str("%7.2f"%o.b_adj).strip(),
       log = log)
   # Update self with new arrays so that H correction knows current R factor.
   # If no H to account for, then this is the final result.
   k_masks       = result.k_masks()
   k_anisotropic = result.k_anisotropic()
   k_isotropic   = result.k_isotropic()
   self.update_core(
     k_mask        = k_masks,
     k_anisotropic = k_anisotropic,
     k_isotropic   = k_isotropic)
   self.show(prefix = "bulk-solvent and scaling", log = log)
   # Consistency check
   assert approx_equal(self.r_all(), r_all_from_scaler)
   # Add contribution from H (if present and riding). This goes to f_part2.
   kh, bh = 0, 0
   if(refine_hd_scattering and
      self.need_to_refine_hd_scattering_contribution()):
     # Obsolete previous contribution f_part2
     f_part2 = fmodel_kbu.f_calc.array(data=fmodel_kbu.f_calc.data()*0)
     self.update_core(f_part2 = f_part2)
     xrs_h = xrs_h.set_occupancies(value=1).set_b_iso(value = 0)
     f_h = self.compute_f_calc(xray_structure = xrs_h)
     # Accumulate all mask contributions: Fcalc_atoms+Fbulk_1+...+Fbulk_N
     data = fmodel_kbu.f_calc.data()
     for k_mask_, f_mask_ in zip(k_masks, fmodel_kbu.f_masks):
       data = data + k_mask_*f_mask_.data()
     f_calc_plus_f_bulk_no_scales = fmodel_kbu.f_calc.array(data = data)
     # Consistency check
     assert approx_equal(self.f_model().data(),
       f_calc_plus_f_bulk_no_scales.data()*k_isotropic*k_anisotropic)
     assert approx_equal(self.f_model_no_scales().data(),
       f_calc_plus_f_bulk_no_scales.data())
     #
     # Compute contribution from H (F_H)
     #
     # Coarse sampling
     b_mean = flex.mean(xrs_no_h.extract_u_iso_or_u_equiv())*adptbx.u_as_b(1.)
     b_min = int(max(0,b_mean)*0.5)
     b_max = int(b_mean*1.5)
     sc = 1000.
     kr=[i/sc for i in range(ifloor(0*sc), iceil(1.5*sc)+1, int(0.1*sc))]
     br=[i/sc for i in range(ifloor(b_min*sc), iceil(b_max*sc)+1, int(5.*sc))]
     o = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
       f_obs       = fmodel_kbu.f_obs.data(),
       f_calc      = f_calc_plus_f_bulk_no_scales.data(),
       f_mask      = f_h.data(),
       k_total     = k_isotropic*k_anisotropic,
       ss          = fmodel_kbu.ss,
       k_sol_range = flex.double(kr),
       b_sol_range = flex.double(br),
       r_ref       = self.r_work())
     if(o.updated()):
       f_part2 = f_h.array(data = o.k_mask()*f_h.data())
       kh, bh = o.k_sol(), o.b_sol()
       self.show(prefix = "add H (%4.2f, %6.2f)"%(kh, bh), log = log, r=o.r())
     # Fine sampling
     k_min = max(0,o.k_sol()-0.1)
     k_max = o.k_sol()+0.1
     b_min = max(0,o.b_sol()-5.)
     b_max = o.b_sol()+5.
     kr=[i/sc for i in range(ifloor(k_min*sc),iceil(k_max*sc)+1,int(0.01*sc))]
     br=[i/sc for i in range(ifloor(b_min*sc),iceil(b_max*sc)+1,int(1.*sc))]
     o = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
       f_obs       = fmodel_kbu.f_obs.data(),
       f_calc      = f_calc_plus_f_bulk_no_scales.data(),
       f_mask      = f_h.data(),
       k_total     = k_isotropic*k_anisotropic,
       ss          = fmodel_kbu.ss,
       k_sol_range = flex.double(kr),
       b_sol_range = flex.double(br),
       r_ref       = o.r())
     if(o.updated()):
       f_part2 = f_h.array(data = o.k_mask()*f_h.data())
       kh, bh = o.k_sol(), o.b_sol()
       self.show(prefix = "add H (%4.2f, %6.2f)"%(kh, bh), log = log, r=o.r())
     # THIS HELPS if fast=true is used, see how it works in reality
     #
     if(fast):
       fmodel_kbu_ = mmtbx.f_model.manager_kbu(
         f_obs   = self.f_obs(),
         f_calc  = f_calc_plus_f_bulk_no_scales,
         f_masks = [f_part2],
         ss      = self.ss)
       result = mmtbx.bulk_solvent.scaler.run_simple(
         fmodel_kbu     = fmodel_kbu_,
         r_free_flags   = self.r_free_flags(),
         bulk_solvent   = params.bulk_solvent,
         bin_selections = self.bin_selections)
       f_part2 = f_part2.array(data = result.core.k_mask()*f_part2.data())
       k_isotropic   = result.core.k_isotropic*result.core.k_isotropic_exp
       k_anisotropic = result.core.k_anisotropic
     # Update self with final scales
     self.update_core(
       k_mask        = k_masks,
       k_anisotropic = k_anisotropic,
       k_isotropic   = k_isotropic,
       f_part2       = f_part2)
     # Make sure what came out of scaling matches what self thinks it really is
     # It must match at least up to 1.e-6.
     self.show(prefix = "add H (%4.2f, %6.2f)"%(kh, bh), log = log)
     if(fast):
       assert approx_equal(result.r_factor(), self.r_work())
     else:
       assert approx_equal(self.r_all(), o.r()), [self.r_all(), o.r()]
   return group_args(
     k_sol  = k_sol,
     b_sol  = b_sol,
     b_cart = b_cart,
     k_h    = kh,
     b_h    = bh,
     b_adj  = b_adj)
Exemplo n.º 4
0
    def update_solvent_and_scale_twin(self, refine_hd_scattering, log):
        if (not self.twinned()): return
        assert len(self.f_masks()) == 1
        # Re-set all scales to unit or zero
        self.show(prefix="update scales twin start", log=log)
        self.reset_all_scales()
        self.show(prefix="reset f_part, k_(total,mask)", log=log)
        f_calc_data = self.f_calc().data()
        f_calc_data_twin = self.f_calc_twin().data()
        # Initial trial set
        sc = 1000.
        ksr = [
            i / sc for i in range(ifloor(0 * sc),
                                  iceil(0.6 * sc) + 1, int(0.05 * sc))
        ]
        bsr = [
            i / sc for i in range(ifloor(0 * sc),
                                  iceil(150. * sc) + 1, int(10. * sc))
        ]
        o_kbu_sol = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
            f_obs=self.f_obs().data(),
            f_calc_1=f_calc_data,
            f_calc_2=f_calc_data_twin,
            f_mask_1=self.arrays.core.f_masks[0].data(),
            f_mask_2=self.arrays.core_twin.f_masks[0].data(),
            ss=self.ss,
            twin_fraction=self.twin_fraction,
            k_sol_range=flex.double(ksr),
            b_sol_range=flex.double(bsr),
            miller_indices=self.f_obs().indices(
            ),  #XXX ??? What about twin-related?
            unit_cell=self.f_obs().unit_cell(),
            r_ref=self.r_all())
        if (o_kbu_sol.updated()):
            self.update(k_mask=o_kbu_sol.k_mask(),
                        k_anisotropic=o_kbu_sol.k_anisotropic())
        # Second (finer) trial set
        k_min = max(o_kbu_sol.k_sol() - 0.05, 0)
        k_max = min(o_kbu_sol.k_sol() + 0.05, 0.6)
        ksr = [
            i / sc for i in range(ifloor(k_min * sc),
                                  iceil(k_max * sc) + 1, int(0.01 * sc))
        ]
        b_min = max(o_kbu_sol.b_sol() - 10, 0)
        b_max = min(o_kbu_sol.b_sol() + 10, 150)
        bsr = [
            i / sc for i in range(ifloor(b_min * sc),
                                  iceil(b_max * sc) + 1, int(1. * sc))
        ]
        o_kbu_sol = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
            f_obs=self.f_obs().data(),
            f_calc_1=f_calc_data,
            f_calc_2=f_calc_data_twin,
            f_mask_1=self.arrays.core.f_masks[0].data(),
            f_mask_2=self.arrays.core_twin.f_masks[0].data(),
            ss=self.ss,
            twin_fraction=self.twin_fraction,
            k_sol_range=flex.double(ksr),
            b_sol_range=flex.double(bsr),
            miller_indices=self.f_obs().indices(
            ),  #XXX ??? What about twin-related?
            unit_cell=self.f_obs().unit_cell(),
            r_ref=o_kbu_sol.r())
        if (o_kbu_sol.updated()):
            self.update(k_mask=o_kbu_sol.k_mask(),
                        k_anisotropic=o_kbu_sol.k_anisotropic())
            # Disable due to rare failures. Technically they should always match. But
            # since different routines are used tiny disagreements are possible.
            # See examples in : /net/anaconda/raid1/afonine/work/bugs/twin_refinement
            #assert approx_equal(self.r_all(), o_kbu_sol.r(), 1.e-5)
            ##############
            # use apply_back_trace in if below
            if (self.xray_structure is not None):
                o = mmtbx.bulk_solvent.scaler.tmp(
                    xray_structure=self.xray_structure,
                    k_anisotropic=o_kbu_sol.k_anisotropic(),
                    k_masks=[o_kbu_sol.k_mask()],
                    ss=self.ss)
                self.update_xray_structure(xray_structure=o.xray_structure,
                                           update_f_calc=True)
                #############
                self.update(k_mask=o.k_masks, k_anisotropic=o.k_anisotropic)

        self.show(prefix="bulk-solvent and scaling", log=log)
        #
        # Add contribution from H (if present and riding). This goes to f_part2.
        #
        kh, bh = 0, 0
        if (refine_hd_scattering
                and self.need_to_refine_hd_scattering_contribution()):
            hd_selection = self.xray_structure.hd_selection()
            xrs_no_h = self.xray_structure.select(~hd_selection)
            xrs_h = self.xray_structure.select(hd_selection)
            # Accumulate all mask contributions: Fcalc_atoms+Fbulk_1+...+Fbulk_N
            data = self.f_calc().data(
            ) + self.f_masks()[0].data() * self.k_masks()[0]
            f_calc_plus_f_bulk_no_scales = self.f_calc().array(data=data)
            data = self.f_calc_twin().data()+\
              self.f_masks_twin()[0].data()*self.k_masks_twin()[0]
            f_calc_plus_f_bulk_no_scales_twin = self.f_calc_twin().array(
                data=data)
            # Initial FH contribution
            xrs_h = xrs_h.set_occupancies(value=1).set_b_iso(value=0)
            f_h = self.compute_f_calc(xray_structure=xrs_h)
            f_h_twin = self.compute_f_calc(xray_structure=xrs_h,
                                           miller_array=self.f_calc_twin())
            # Coarse sampling
            b_mean = flex.mean(
                xrs_no_h.extract_u_iso_or_u_equiv()) * adptbx.u_as_b(1.)
            b_min = int(max(0, b_mean) * 0.5)
            b_max = int(b_mean * 1.5)
            sc = 1000.
            kr = [
                i / sc for i in range(ifloor(0 * sc),
                                      iceil(1.5 * sc) + 1, int(0.1 * sc))
            ]
            br = [
                i / sc for i in range(ifloor(b_min * sc),
                                      iceil(b_max * sc) + 1, int(5. * sc))
            ]
            obj = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
                f_obs=self.f_obs().data(),
                f_calc_1=f_calc_plus_f_bulk_no_scales.data(),
                f_calc_2=f_calc_plus_f_bulk_no_scales_twin.data(),
                f_mask_1=f_h.data(),
                f_mask_2=f_h_twin.data(),
                ss=self.ss,
                twin_fraction=self.twin_fraction,
                k_sol_range=flex.double(kr),
                b_sol_range=flex.double(br),
                miller_indices=self.f_obs().indices(
                ),  # XXX What about twin-related?
                unit_cell=self.f_obs().unit_cell(),
                r_ref=self.r_work())
            if (obj.updated()):
                f_part2 = f_h.array(data=obj.k_mask() * f_h.data())
                f_part2_twin = f_h_twin.array(data=obj.k_mask() *
                                              f_h_twin.data())
                kh, bh = obj.k_sol(), obj.b_sol()
            # Fine sampling
            k_min = max(0, obj.k_sol() - 0.1)
            k_max = obj.k_sol() + 0.1
            b_min = max(0, obj.b_sol() - 5.)
            b_max = obj.b_sol() + 5.
            kr = [
                i / sc for i in range(ifloor(k_min * sc),
                                      iceil(k_max * sc) + 1, int(0.01 * sc))
            ]
            br = [
                i / sc for i in range(ifloor(b_min * sc),
                                      iceil(b_max * sc) + 1, int(5. * sc))
            ]
            obj = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
                f_obs=self.f_obs().data(),
                f_calc_1=f_calc_plus_f_bulk_no_scales.data(),
                f_calc_2=f_calc_plus_f_bulk_no_scales_twin.data(),
                f_mask_1=f_h.data(),
                f_mask_2=f_h_twin.data(),
                ss=self.ss,
                twin_fraction=self.twin_fraction,
                k_sol_range=flex.double(kr),
                b_sol_range=flex.double(br),
                miller_indices=self.f_obs().indices(
                ),  # XXX What about twin-related?
                unit_cell=self.f_obs().unit_cell(),
                r_ref=obj.r())
            if (obj.updated()):
                f_part2 = f_h.array(data=obj.k_mask() * f_h.data())
                f_part2_twin = f_h_twin.array(data=obj.k_mask() *
                                              f_h_twin.data())
                kh, bh = obj.k_sol(), obj.b_sol()
            self.update_core(f_part2=f_part2,
                             f_part2_twin=f_part2_twin,
                             k_anisotropic=obj.k_anisotropic())
            self.show(prefix="add H (%4.2f, %6.2f)" % (kh, bh), log=log)
        b_cart = adptbx.u_as_b(
            adptbx.u_star_as_u_cart(self.f_obs().unit_cell(),
                                    o_kbu_sol.u_star()))
        return group_args(k_sol=o_kbu_sol.k_sol(),
                          b_sol=o_kbu_sol.b_sol(),
                          b_cart=b_cart,
                          k_h=kh,
                          b_h=bh)
Exemplo n.º 5
0
 def update_solvent_and_scale_2(self, fast, params, apply_back_trace,
                                refine_hd_scattering, log):
     if (params is None): params = bss.master_params.extract()
     if (self.xray_structure is not None):
         # Figure out Fcalc and Fmask based on presence of H
         hd_selection = self.xray_structure.hd_selection()
         xrs_no_h = self.xray_structure.select(~hd_selection)
         xrs_h = self.xray_structure.select(hd_selection)
     # Create data container for scalers. If H scattering is refined then it is
     # assumed that self.f_calc() does not contain H contribution at all.
     fmodel_kbu = mmtbx.f_model.manager_kbu(f_obs=self.f_obs(),
                                            f_calc=self.f_calc(),
                                            f_masks=self.f_masks(),
                                            ss=self.ss)
     # Compute k_total and k_mask using one of the two methods (anal or min).
     # Note: this intentionally ignores previously existing f_part1 and f_part2.
     #
     k_sol, b_sol, b_cart, b_adj = [
         None,
     ] * 4
     if (fast):  # analytical
         assert len(fmodel_kbu.f_masks) == 1
         result = mmtbx.bulk_solvent.scaler.run_simple(
             fmodel_kbu=fmodel_kbu,
             r_free_flags=self.r_free_flags(),
             bulk_solvent=params.bulk_solvent,
             bin_selections=self.bin_selections)
         r_all_from_scaler = result.r_all(
         )  # must be here, before apply_back_trace
     else:  # using minimization: exp solvent and scale model (k_sol,b_sol,b_cart)
         result = bss.bulk_solvent_and_scales(fmodel_kbu=fmodel_kbu,
                                              params=params)
         k_sol, b_sol, b_cart = result.k_sols(), result.b_sols(
         ), result.b_cart()
         r_all_from_scaler = result.r_all(
         )  # must be here, before apply_back_trace
     if (apply_back_trace and len(fmodel_kbu.f_masks) == 1
             and self.xray_structure is not None):
         o = result.apply_back_trace_of_overall_exp_scale_matrix(
             xray_structure=self.xray_structure)
         b_adj = o.b_adj
         if (not fast): b_sol, b_cart = [o.b_sol], o.b_cart
         self.update_xray_structure(xray_structure=o.xray_structure,
                                    update_f_calc=True)
         fmodel_kbu = fmodel_kbu.update(f_calc=self.f_calc())
         self.show(prefix="overall B=%s to atoms" %
                   str("%7.2f" % o.b_adj).strip(),
                   log=log)
     # Update self with new arrays so that H correction knows current R factor.
     # If no H to account for, then this is the final result.
     k_masks = result.k_masks()
     k_anisotropic = result.k_anisotropic()
     k_isotropic = result.k_isotropic()
     self.update_core(k_mask=k_masks,
                      k_anisotropic=k_anisotropic,
                      k_isotropic=k_isotropic)
     self.show(prefix="bulk-solvent and scaling", log=log)
     # Consistency check
     if (not apply_back_trace):
         assert approx_equal(self.r_all(), r_all_from_scaler)
     # Add contribution from H (if present and riding). This goes to f_part2.
     kh, bh = 0, 0
     if (refine_hd_scattering
             and self.need_to_refine_hd_scattering_contribution()):
         # Obsolete previous contribution f_part2
         f_part2 = fmodel_kbu.f_calc.array(data=fmodel_kbu.f_calc.data() *
                                           0)
         self.update_core(f_part2=f_part2)
         xrs_h = xrs_h.set_occupancies(value=1).set_b_iso(value=0)
         f_h = self.compute_f_calc(xray_structure=xrs_h)
         # Accumulate all mask contributions: Fcalc_atoms+Fbulk_1+...+Fbulk_N
         data = fmodel_kbu.f_calc.data()
         for k_mask_, f_mask_ in zip(k_masks, fmodel_kbu.f_masks):
             data = data + k_mask_ * f_mask_.data()
         f_calc_plus_f_bulk_no_scales = fmodel_kbu.f_calc.array(data=data)
         # Consistency check
         assert approx_equal(
             self.f_model().data(),
             f_calc_plus_f_bulk_no_scales.data() * k_isotropic *
             k_anisotropic)
         assert approx_equal(self.f_model_no_scales().data(),
                             f_calc_plus_f_bulk_no_scales.data())
         #
         # Compute contribution from H (F_H)
         #
         # Coarse sampling
         b_mean = flex.mean(
             xrs_no_h.extract_u_iso_or_u_equiv()) * adptbx.u_as_b(1.)
         b_min = int(max(0, b_mean) * 0.5)
         b_max = int(b_mean * 1.5)
         sc = 1000.
         kr = [
             i / sc for i in range(ifloor(0 * sc),
                                   iceil(1.5 * sc) + 1, int(0.1 * sc))
         ]
         br = [
             i / sc for i in range(ifloor(b_min * sc),
                                   iceil(b_max * sc) + 1, int(5. * sc))
         ]
         o = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
             f_obs=fmodel_kbu.f_obs.data(),
             f_calc=f_calc_plus_f_bulk_no_scales.data(),
             f_mask=f_h.data(),
             k_total=k_isotropic * k_anisotropic,
             ss=fmodel_kbu.ss,
             k_sol_range=flex.double(kr),
             b_sol_range=flex.double(br),
             r_ref=self.r_work())
         if (o.updated()):
             f_part2 = f_h.array(data=o.k_mask() * f_h.data())
             kh, bh = o.k_sol(), o.b_sol()
             self.show(prefix="add H (%4.2f, %6.2f)" % (kh, bh),
                       log=log,
                       r=o.r())
         # Fine sampling
         k_min = max(0, o.k_sol() - 0.1)
         k_max = o.k_sol() + 0.1
         b_min = max(0, o.b_sol() - 5.)
         b_max = o.b_sol() + 5.
         kr = [
             i / sc for i in range(ifloor(k_min * sc),
                                   iceil(k_max * sc) + 1, int(0.01 * sc))
         ]
         br = [
             i / sc for i in range(ifloor(b_min * sc),
                                   iceil(b_max * sc) + 1, int(1. * sc))
         ]
         o = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
             f_obs=fmodel_kbu.f_obs.data(),
             f_calc=f_calc_plus_f_bulk_no_scales.data(),
             f_mask=f_h.data(),
             k_total=k_isotropic * k_anisotropic,
             ss=fmodel_kbu.ss,
             k_sol_range=flex.double(kr),
             b_sol_range=flex.double(br),
             r_ref=o.r())
         if (o.updated()):
             f_part2 = f_h.array(data=o.k_mask() * f_h.data())
             kh, bh = o.k_sol(), o.b_sol()
             self.show(prefix="add H (%4.2f, %6.2f)" % (kh, bh),
                       log=log,
                       r=o.r())
         # THIS HELPS if fast=true is used, see how it works in reality
         #
         if (fast):
             fmodel_kbu_ = mmtbx.f_model.manager_kbu(
                 f_obs=self.f_obs(),
                 f_calc=f_calc_plus_f_bulk_no_scales,
                 f_masks=[f_part2],
                 ss=self.ss)
             result = mmtbx.bulk_solvent.scaler.run_simple(
                 fmodel_kbu=fmodel_kbu_,
                 r_free_flags=self.r_free_flags(),
                 bulk_solvent=params.bulk_solvent,
                 bin_selections=self.bin_selections)
             f_part2 = f_part2.array(data=result.core.k_mask() *
                                     f_part2.data())
             k_isotropic = result.core.k_isotropic * result.core.k_isotropic_exp
             k_anisotropic = result.core.k_anisotropic
         # Update self with final scales
         self.update_core(k_mask=k_masks,
                          k_anisotropic=k_anisotropic,
                          k_isotropic=k_isotropic,
                          f_part2=f_part2)
         # Make sure what came out of scaling matches what self thinks it really is
         # It must match at least up to 1.e-6.
         self.show(prefix="add H (%4.2f, %6.2f)" % (kh, bh), log=log)
         if (fast):
             assert approx_equal(result.r_work(), self.r_work(), 1.e-4)
         else:
             assert approx_equal(self.r_all(), o.r()), [self.r_all(), o.r()]
     return group_args(k_sol=k_sol,
                       b_sol=b_sol,
                       b_cart=b_cart,
                       k_h=kh,
                       b_h=bh,
                       b_adj=b_adj)
  def _ksol_bsol_grid_search(self):
    # XXX HERE
    start_r_factor = self.fmodel_kbu.r_factor()
    final_ksol   = self.fmodel_kbu.data.k_sols()
    final_bsol   = self.fmodel_kbu.data.b_sols()
    final_b_cart = self.fmodel_kbu.b_cart()
    final_r_factor = start_r_factor

    k_sols = kb_range(0.6,
                      0.0,
                      0.1)
    b_sols = kb_range(80.,
                      10,
                      5)
    assert len(self.fmodel_kbu.f_masks)==1
    o = bulk_solvent.k_sol_b_sol_k_anisotropic_scaler_twin(
      f_obs          = self.fmodel_kbu.f_obs.data(),
      f_calc         = self.fmodel_kbu.f_calc.data(),
      f_mask         = self.fmodel_kbu.f_masks[0].data(),
      ss             = self.fmodel_kbu.ss,
      k_sol_range    = flex.double(k_sols),
      b_sol_range    = flex.double(b_sols),
      miller_indices = self.fmodel_kbu.f_obs.indices(),
      r_ref          = start_r_factor)
    if(o.updated()):
      assert o.r() < start_r_factor
      final_r_factor = o.r()
      final_ksol     = o.k_sol()
      final_bsol     = o.b_sol()
      final_b_cart   = adptbx.u_as_b(adptbx.u_star_as_u_cart(
        self.fmodel_kbu.f_obs.unit_cell(), o.u_star()))
      self.fmodel_kbu.update(
        k_sols=[final_ksol],
        b_sols=[final_bsol],
        b_cart=final_b_cart)
      assert self.fmodel_kbu.r_factor() <= start_r_factor
      if(final_ksol < 0.01):
        final_ksol=0
        self.fmodel_kbu.update(
          k_sols=[final_ksol])
        final_r_factor = self.fmodel_kbu.r_factor()
      else:
        o = k_sol_b_sol_b_cart_minimizer(
          fmodel_kbu = self.fmodel_kbu,
          refine_kbu = True)
        if(o.kbu.r_factor() < final_r_factor):
          final_b_cart = adptbx.u_as_b(adptbx.u_star_as_u_cart(
            self.fmodel_kbu.f_obs.unit_cell(), o.kbu.u_star()))
          final_ksol = list(o.kbu.k_sols())
          final_bsol = list(o.kbu.b_sols())
          self.fmodel_kbu.update(
            k_sols=final_ksol,
            b_sols=final_bsol,
            b_cart=final_b_cart)
        else:
          self.fmodel_kbu.update(
            k_sols=[final_ksol],
            b_sols=[final_bsol],
            b_cart=final_b_cart)
        final_r_factor = self.fmodel_kbu.r_factor()
        assert self.fmodel_kbu.r_factor() <= start_r_factor
    self.fmodel_kbu.update(
      k_sols = final_ksol,
      b_sols = final_bsol,
      b_cart = final_b_cart)
    assert abs(self.fmodel_kbu.r_factor()-final_r_factor) < 1.e-6
    assert self.fmodel_kbu.r_factor() <= start_r_factor
    return final_ksol, final_bsol, final_b_cart, final_r_factor