def exercise_mask_data_1(space_group_info, n_sites=100):
    from cctbx import maptbx
    from cctbx.masks import vdw_radii_from_xray_structure
    for d_min in [1, 1.5, 2.1]:
        for resolution_factor in [1. / 2, 1. / 3, 1. / 4, 1. / 5]:
            xrs = random_structure.xray_structure(
                space_group_info=space_group_info,
                elements=(("O", "N", "C") * (n_sites // 3 + 1))[:n_sites],
                volume_per_atom=30,
                min_distance=1)
            atom_radii = vdw_radii_from_xray_structure(xray_structure=xrs)
            asu_mask = masks.atom_mask(unit_cell=xrs.unit_cell(),
                                       group=xrs.space_group(),
                                       resolution=d_min,
                                       grid_step_factor=resolution_factor,
                                       solvent_radius=1.0,
                                       shrink_truncation_radius=1.0)
            asu_mask.compute(xrs.sites_frac(), atom_radii)
            mask_data = asu_mask.mask_data_whole_uc()
            assert flex.min(mask_data) == 0.0
            # It's not just 0 and 1 ...
            assert flex.max(mask_data) == xrs.space_group().order_z()
            # In fact, it is a mixture ...
            if 0:  # XXX this will rightfully crash
                mask_data_ = mask_data / xrs.space_group().order_z()
                s0 = mask_data_ < 0.5
                s1 = mask_data_ > 0.5
                if (mask_data_.size() != s0.count(True) + s1.count(True)):
                    for d in mask_data_:
                        if (d != 0 and d != 1):
                            print(d, xrs.space_group().order_z())
                    assert mask_data_.size(
                    ) == s0.count(True) + s1.count(True), [
                        mask_data_.size() - (s0.count(True) + s1.count(True))
                    ]
            if (
                    0
            ):  # XXX This would crash with the message: "... The grid is not ..."
                cr_gr = maptbx.crystal_gridding(
                    unit_cell=xrs.unit_cell(),
                    d_min=d_min,
                    resolution_factor=resolution_factor)
                asu_mask = masks.atom_mask(unit_cell=xrs.unit_cell(),
                                           space_group=xrs.space_group(),
                                           gridding_n_real=cr_gr.n_real(),
                                           solvent_radius=1.0,
                                           shrink_truncation_radius=1.0)
                asu_mask.compute(xrs.sites_frac(), atom_radii)
def exercise_mask_data_1(space_group_info, n_sites=100):
  from cctbx import maptbx
  from cctbx.masks import vdw_radii_from_xray_structure
  for d_min in [1, 1.5, 2.1]:
    for resolution_factor in [1./2, 1./3, 1./4, 1./5]:
      xrs = random_structure.xray_structure(
        space_group_info=space_group_info,
        elements=(("O","N","C")*(n_sites//3+1))[:n_sites],
        volume_per_atom=30,
        min_distance=1)
      atom_radii = vdw_radii_from_xray_structure(xray_structure = xrs)
      asu_mask = masks.atom_mask(
        unit_cell                = xrs.unit_cell(),
        group                    = xrs.space_group(),
        resolution               = d_min,
        grid_step_factor         = resolution_factor,
        solvent_radius           = 1.0,
        shrink_truncation_radius = 1.0)
      asu_mask.compute(xrs.sites_frac(), atom_radii)
      mask_data = asu_mask.mask_data_whole_uc()
      assert flex.min(mask_data) == 0.0
      # It's not just 0 and 1 ...
      assert flex.max(mask_data) == xrs.space_group().order_z()
      # In fact, it is a mixture ...
      if 0: # XXX this will rightfully crash
        mask_data_ = mask_data / xrs.space_group().order_z()
        s0 = mask_data_ < 0.5
        s1 = mask_data_ > 0.5
        if(mask_data_.size() != s0.count(True)+s1.count(True)):
          for d in mask_data_:
            if(d != 0 and d != 1): print d, xrs.space_group().order_z()
          assert mask_data_.size() == s0.count(True)+s1.count(True), [
            mask_data_.size()-(s0.count(True)+s1.count(True))]
      if(0): # XXX This would crash with the message: "... The grid is not ..."
        cr_gr = maptbx.crystal_gridding(
          unit_cell         = xrs.unit_cell(),
          d_min             = d_min,
          resolution_factor = resolution_factor)
        asu_mask = masks.atom_mask(
          unit_cell                = xrs.unit_cell(),
          space_group              = xrs.space_group(),
          gridding_n_real          = cr_gr.n_real(),
          solvent_radius           = 1.0,
          shrink_truncation_radius = 1.0)
        asu_mask.compute(xrs.sites_frac(), atom_radii)
def exercise_mask_data_2(space_group_info,
                         n_sites=100,
                         d_min=2.0,
                         resolution_factor=1. / 4):
    from cctbx import maptbx
    from cctbx.masks import vdw_radii_from_xray_structure
    for yn2 in [0, 1]:
        for yn in [0, 1]:
            xrs = random_structure.xray_structure(
                space_group_info=space_group_info,
                elements=(("O", "N", "C") * (n_sites // 3 + 1))[:n_sites],
                volume_per_atom=50,
                min_distance=1.5)
            xrs.shake_sites_in_place(mean_distance=10)
            if (yn2): xrs = xrs.expand_to_p1(sites_mod_positive=True)
            atom_radii = vdw_radii_from_xray_structure(xray_structure=xrs)
            asu_mask = masks.atom_mask(unit_cell=xrs.unit_cell(),
                                       group=xrs.space_group(),
                                       resolution=d_min,
                                       grid_step_factor=resolution_factor,
                                       solvent_radius=1.0,
                                       shrink_truncation_radius=1.0)
            asu_mask.compute(xrs.sites_frac(), atom_radii)
            mask_data = asu_mask.mask_data_whole_uc()
            #
            xrs_p1 = xrs.expand_to_p1(sites_mod_positive=True)
            for site_frac in xrs_p1.sites_frac():
                mv = mask_data.value_at_closest_grid_point(site_frac)
                assert mv == 0
            #
            mask_data = mask_data / xrs.space_group().order_z()
            if (yn == 1):
                mask_data = maptbx.copy(mask_data,
                                        flex.grid(mask_data.focus()))
            #
            for site_frac in xrs_p1.sites_frac():
                mv = mask_data.value_at_closest_grid_point(site_frac)
                assert mv == 0
            #
            fc = xrs.structure_factors(d_min=d_min).f_calc()
            f_mask_1 = fc.set().array(
                data=asu_mask.structure_factors(fc.indices()))
            f_mask_2 = f_mask_1.structure_factors_from_map(
                map=mask_data,
                use_scale=True,
                anomalous_flag=False,
                use_sg=True)
            fm1 = abs(f_mask_1).data()
            fm2 = abs(f_mask_2).data()
            r = flex.sum(flex.abs(fm1 - fm2)) / flex.sum(fm1 + fm2)
            assert approx_equal(r, 0.0)
def exercise_mask_data_2(space_group_info, n_sites=100, d_min=2.0,
                         resolution_factor=1./4):
  from cctbx import maptbx
  from cctbx.masks import vdw_radii_from_xray_structure
  for yn2 in [0,1]:
    for yn in [0,1]:
      xrs = random_structure.xray_structure(
        space_group_info=space_group_info,
        elements=(("O","N","C")*(n_sites//3+1))[:n_sites],
        volume_per_atom=50,
        min_distance=1.5)
      xrs.shake_sites_in_place(mean_distance=10)
      if(yn2): xrs = xrs.expand_to_p1(sites_mod_positive=True)
      atom_radii = vdw_radii_from_xray_structure(xray_structure = xrs)
      asu_mask = masks.atom_mask(
        unit_cell                = xrs.unit_cell(),
        group                    = xrs.space_group(),
        resolution               = d_min,
        grid_step_factor         = resolution_factor,
        solvent_radius           = 1.0,
        shrink_truncation_radius = 1.0)
      asu_mask.compute(xrs.sites_frac(), atom_radii)
      mask_data = asu_mask.mask_data_whole_uc()
      #
      xrs_p1 = xrs.expand_to_p1(sites_mod_positive=True)
      for site_frac in xrs_p1.sites_frac():
        mv = mask_data.value_at_closest_grid_point(site_frac)
        assert mv == 0
      #
      mask_data = mask_data / xrs.space_group().order_z()
      if(yn == 1):
        mask_data = maptbx.copy(mask_data, flex.grid(mask_data.focus()))
      #
      for site_frac in xrs_p1.sites_frac():
        mv = mask_data.value_at_closest_grid_point(site_frac)
        assert mv == 0
      #
      fc = xrs.structure_factors(d_min = d_min).f_calc()
      f_mask_1 = fc.set().array(data = asu_mask.structure_factors(fc.indices()))
      f_mask_2 = f_mask_1.structure_factors_from_map(map=mask_data,
        use_scale = True, anomalous_flag = False, use_sg = True)
      fm1 = abs(f_mask_1).data()
      fm2 = abs(f_mask_2).data()
      r = flex.sum( flex.abs( fm1 - fm2 ) ) / flex.sum( fm1 + fm2 )
      assert approx_equal(r, 0.0)
def compare_masks(struc, opts):
  tolerance = opts.tolerance
  resolution = opts.resolution
  solvent_radius = opts.solvent_radius
  shrink_radius = opts.shrink_radius
  verbose = opts.verbose
  cout.truncate(0)
  time_p1 = 0.0
  time_asu = 0.0
  time_orig = 0.0
  params = masks.mask_master_params.extract()
  params.ignore_hydrogens = False
  params.ignore_zero_occupancy_atoms = False
  params.solvent_radius = solvent_radius
  params.shrink_truncation_radius = shrink_radius
  fc = struc.structure_factors(d_min = resolution).f_calc()
  while fc.data().size() <= 3 :
    resolution /= 1.2
    assert resolution > 1.0E-3
    fc = struc.structure_factors( d_min = resolution).f_calc()
  print >>cout, "Resolution= ", resolution, "  solvent radius= ", \
      solvent_radius, "  shrink radius= ", shrink_radius,  "  Tolerance= ", \
      tolerance, "  Number of reflection= ", fc.data().size()
  struc.show_summary(cout)
  group = struc.space_group()
  print >>cout, "Cell volume= ", struc.unit_cell().volume(), \
    "  Group order= ", group.order_z(), " p= ", group.order_p()
  print >>cout, "Hall  symbol: ", group.type().hall_symbol()
  #check_group(group)

  tb = time.time()
  asu_mask = masks.atom_mask(
      unit_cell = struc.unit_cell(),
      group = struc.space_group(),
      resolution = fc.d_min(),
      grid_step_factor = params.grid_step_factor,
      solvent_radius = params.solvent_radius,
      shrink_truncation_radius = params.shrink_truncation_radius )
  te = time.time()
  time_asu += (te-tb)
  grid =  asu_mask.grid_size()
  print >>cout, "asu mask grid = ", grid
  zero_test(asu_mask, fc, tolerance = tolerance)
  radii = get_radii(struc)
  assert len(radii) == len(struc.sites_frac())
  tb = time.time()
  asu_mask.compute( struc.sites_frac(), radii )
  te = time.time()
  time_asu += (te-tb)
  print >>cout, "   n asu atoms= ", asu_mask.n_asu_atoms(), \
      "   has-enclosed= ", asu_mask.debug_has_enclosed_box
  tb = time.time()
  fm_asu = asu_mask.structure_factors( fc.indices() )
  fm_asu = fc.set().array( data = fm_asu )
  te = time.time()
  time_asu_sf = te-tb
  time_asu += (te-tb)
  # save files
  if not opts.save_files is None:
    tmp_file = open(opts.save_files + ".pdb", "w")
    print >>tmp_file, struc.as_pdb_file()
    tmp_file.close()
    asu_mask.xplor_write_map(opts.save_files + "_mask.map")
    asu_mask.xplor_write_map(opts.save_files + "_inverted_mask.map", 1, True)
    # also save structure factors
    import iotbx.mtz
    mtzo = iotbx.mtz.object()
    mtzo.set_title("mask test")
    mtzo.add_history(line="start")
    mtzo.set_space_group_info(fm_asu.space_group_info())
    mtzo.set_hkl_base(fm_asu.unit_cell())
    crystal = mtzo.add_crystal(
      name="mask_test_crystal",
      project_name="mask_test_project",
      unit_cell=fm_asu.unit_cell())
    dataset = crystal.add_dataset(
      name="mask_test_dataset",
      wavelength=1)
    assert dataset.add_miller_array(
      miller_array=fm_asu,
      column_root_label="F",
      #column_types=column_types
      ) is dataset
    mtzo.add_history(line="done")
    mtzo.write(opts.save_files + "_sf.mtz")
  #
  # ========= old mask =============
  #
  tb = time.time()
  struc_p1 = struc.expand_to_p1()
  te = time.time()
  time_p1_exp = (te-tb)
  time_p1 += (te-tb)
  fc_p1 = fc.deep_copy()
  fc_p1 = fc_p1.customized_copy(crystal_symmetry = struc_p1.crystal_symmetry())
  tb = time.time()
  blk_p1 = masks.bulk_solvent(
    xray_structure = struc_p1,
    gridding_n_real = grid,
    ignore_zero_occupancy_atoms = params.ignore_zero_occupancy_atoms,
    ignore_hydrogen_atoms = params.ignore_hydrogens,
    solvent_radius = params.solvent_radius,
    shrink_truncation_radius = params.shrink_truncation_radius)
  te = time.time()
  time_p1_msk = (te-tb)
  time_p1 += (te-tb)
  tb = time.time()
  fm_p1 = blk_p1.structure_factors( miller_set = fc_p1 )
  te = time.time()
  time_p1_sf = (te-tb)
  time_p1 += (te-tb)
  blk_p1.show_summary(cout)
  ### original mask
  tb = time.time()
  blk_o = masks.bulk_solvent(
    xray_structure = struc,
    gridding_n_real = grid,
    ignore_zero_occupancy_atoms = params.ignore_zero_occupancy_atoms,
    ignore_hydrogen_atoms = params.ignore_hydrogens,
    solvent_radius = params.solvent_radius,
    shrink_truncation_radius = params.shrink_truncation_radius)
  te = time.time()
  time_orig_msk = (te-tb)
  time_orig += (te-tb)
  tb = time.time()
  fm_o = blk_o.structure_factors( miller_set = fc )
  te = time.time()
  time_orig_sf = (te-tb)
  time_orig += (te-tb)
  print >>cout, "Number of reflections ::: Fm asu = ", fm_asu.data().size(), \
    "Fm P1 = ", fm_p1.data().size()
  print >>cout, "Time ( ms )    P1= ", time_p1*1000.0, "   orig= ", \
      time_orig*1000.0, "    asu= ", time_asu*1000.0
  print >>cout, "Times ( ms ) mask_asu= ", asu_mask.debug_mask_asu_time, \
      " atoms_to_asu= ", asu_mask.debug_atoms_to_asu_time, \
      " accessible= ", asu_mask.debug_accessible_time, \
      " contact= ", asu_mask.debug_contact_time, \
      " Fc= ", time_asu_sf*1000.0, \
      " fft= ", asu_mask.debug_fft_time
  print >>cout, "Times ( ms ) orig:  mask= ", time_orig_msk*1000.0, "  Fc=", \
      time_orig_sf*1000.0
  print >>cout, "Times ( ms ) p1 :  expand= ", time_p1_exp*1000.0, "  mask= ", \
      time_p1_msk*1000.0, "  Fc=", time_p1_sf*1000.0
  assert fm_asu.data().size() == fm_o.data().size()
  t_v1 = asu_mask.contact_surface_fraction
  t_v2 = blk_p1.contact_surface_fraction
  t_v3 = max( abs(t_v1), abs(t_v2) )
  if t_v3 > 1.0E-6:
    t_v4 = abs( t_v1 - t_v2 ) / t_v3
  else:
    t_v4 = 0.0
  if( t_v4>1.0E-6 ):
    if not opts.failed_file is None:
      tmp_file = open(opts.failed_file, "w")
      print >>tmp_file, struc.as_pdb_file()
      tmp_file.close()
    raise "Not equal solvent volume"

  assert approx_equal(
    asu_mask.contact_surface_fraction, blk_p1.contact_surface_fraction)
  assert approx_equal(
    asu_mask.accessible_surface_fraction, blk_p1.accessible_surface_fraction)
  assert is_below_limit(
    value=asu_mask.accessible_surface_fraction,
    limit=asu_mask.contact_surface_fraction)
  n_compared = compare_fc(fm_asu, fm_p1, tolerance = tolerance)
  assert n_compared == fm_asu.data().size(), \
    "N compared refls: "+str(n_compared) + " != " + str(fm_asu.data().size())
  assert n_compared >0
  if verbose:
    print cout.getvalue()
  # test that second calculation will produce the same results
  asu_mask.compute( struc.sites_frac(), radii )
  fm_asu2 = asu_mask.structure_factors( fc.indices() )
  fm_asu2 = fc.set().array( data = fm_asu2 )
  n_compared = compare_fc(fm_asu, fm_asu2, tolerance = tolerance)
  assert n_compared == fm_asu.data().size(), \
    "N compared refls: "+str(n_compared) + " != " + str(fm_asu.data().size())
  cout.truncate(0)