Example #1
0
def test_radius(setup):
    s0 = setup["beam"].get_s0()
    m2 = setup["gonio"].get_rotation_axis()
    s0_length = matrix.col(setup["beam"].get_s0()).length()

    width, height = setup["detector"][0].get_image_size()
    radius12 = setup["delta_divergence"]

    for i in range(1000):

        # Get random x, y, z
        x = random.uniform(0, 2000)
        y = random.uniform(0, 2000)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = (
            matrix.col(setup["detector"][0].get_pixel_lab_coord((x, y))).normalize()
            * s0_length
        )
        phi = setup["scan"].get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = setup["calculate_bbox"](s1, z, panel)

        # Create the XDS coordinate system
        xcs = CoordinateSystem(m2, s0, s1, phi)

        # Check vertical edges
        for j in range(bbox[2], bbox[3] + 1):
            xyz1 = setup["detector"][0].get_pixel_lab_coord((bbox[0], j))
            xyz2 = setup["detector"][0].get_pixel_lab_coord((bbox[1] + 1, j))
            sdash1 = matrix.col(xyz1).normalize() * s0_length
            sdash2 = matrix.col(xyz2).normalize() * s0_length
            e11, e21, e31 = xcs.from_beam_vector_and_rotation_angle(sdash1, phi)
            e12, e22, e31 = xcs.from_beam_vector_and_rotation_angle(sdash2, phi)
            if bbox[0] > 0 and bbox[1] < width:
                assert math.sqrt(e11 ** 2 + e21 ** 2) >= radius12
                assert math.sqrt(e12 ** 2 + e22 ** 2) >= radius12

        # Check horizontal edges
        for i in range(bbox[0], bbox[1] + 1):
            xyz1 = setup["detector"][0].get_pixel_lab_coord((i, bbox[2]))
            xyz2 = setup["detector"][0].get_pixel_lab_coord((i, bbox[3] + 1))
            sdash1 = matrix.col(xyz1).normalize() * s0_length
            sdash2 = matrix.col(xyz2).normalize() * s0_length
            e11, e21, e32 = xcs.from_beam_vector_and_rotation_angle(sdash1, phi)
            e12, e22, e32 = xcs.from_beam_vector_and_rotation_angle(sdash2, phi)
            if bbox[2] > 0 and bbox[3] < height:
                assert math.sqrt(e11 ** 2 + e21 ** 2) >= radius12
                assert math.sqrt(e12 ** 2 + e22 ** 2) >= radius12
Example #2
0
    def __call__(self):

        from scitbx import matrix
        from random import uniform
        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem

        s0 = self.beam.get_s0()
        m2 = self.gonio.get_rotation_axis()
        s0_length = matrix.col(self.beam.get_s0()).length()

        for i in range(100):

            # Get random x, y, z
            x = uniform(0, 2000)
            y = uniform(0, 2000)
            z = uniform(0, 9)

            # Get random s1, phi, panel
            s1 = matrix.col(self.detector[0].get_pixel_lab_coord(
                (x, y))).normalize() * s0_length
            phi = self.scan.get_angle_from_array_index(z, deg=False)
            panel = 0

            # Calculate the bounding box
            bbox = self.calculate_bbox(s1, phi, panel)
            x1, x2 = bbox[0], bbox[1]
            y1, y2 = bbox[2], bbox[3]
            z1, z2 = bbox[4], bbox[5]

            # Create the XDS coordinate system
            xcs = CoordinateSystem(m2, s0, s1, phi)

            # Calculate the transform fraction
            forward_fraction = self.transform_forward(bbox[4:], phi,
                                                      xcs.zeta())

            # Calculate the transform fraction
            reverse_fraction = self.transform_reverse(bbox[4:], phi,
                                                      xcs.zeta())

            # Check the same points are non-zero
            eps = 1e-7
            for j in range(forward_fraction.all()[0]):
                for i in range(forward_fraction.all()[1]):
                    if forward_fraction[j, i] > 0.0:
                        assert (reverse_fraction[i, j] > 0.0)
                    else:
                        assert (reverse_fraction[i, j] < eps)

        # Test passed
        print 'OK'
Example #3
0
  def __call__(self):

    from scitbx import matrix
    from random import uniform
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem

    s0 = self.beam.get_s0()
    m2 = self.gonio.get_rotation_axis()
    s0_length = matrix.col(self.beam.get_s0()).length()

    for i in range(100):

      # Get random x, y, z
      x = uniform(0, 2000)
      y = uniform(0, 2000)
      z = uniform(0, 9)

      # Get random s1, phi, panel
      s1 = matrix.col(self.detector[0].get_pixel_lab_coord(
          (x, y))).normalize() * s0_length
      phi = self.scan.get_angle_from_array_index(z, deg=False)
      panel = 0

      # Calculate the bounding box
      bbox = self.calculate_bbox(s1, phi, panel)
      x1, x2 = bbox[0], bbox[1]
      y1, y2 = bbox[2], bbox[3]
      z1, z2 = bbox[4], bbox[5]

      # Create the XDS coordinate system
      xcs = CoordinateSystem(m2, s0, s1, phi)

      # Calculate the transform fraction
      forward_fraction = self.transform_forward(bbox[4:], phi, xcs.zeta())

      # Calculate the transform fraction
      reverse_fraction = self.transform_reverse(bbox[4:], phi, xcs.zeta())

      # Check the same points are non-zero
      eps = 1e-7
      for j in range(forward_fraction.all()[0]):
        for i in range(forward_fraction.all()[1]):
          if forward_fraction[j,i] > 0.0:
            assert(reverse_fraction[i,j] > 0.0)
          else:
            assert(reverse_fraction[i,j] < eps)

    # Test passed
    print 'OK'
Example #4
0
class Test(object):
    def __init__(self):
        from dials.algorithms.profile_model.gaussian_rs import transform
        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
        import os
        import libtbx.load_env
        from math import floor
        from scitbx import matrix
        from dials.model.serialize import load
        from random import uniform

        try:
            dials_regression = libtbx.env.dist_path('dials_regression')
        except KeyError, e:
            print 'FAIL: dials_regression not configured'
            exit(0)

        # Set the sweep filename and load the sweep
        filename = os.path.join(dials_regression, 'centroid_test_data',
                                'sweep.json')
        self.sweep = load.sweep(filename)

        # Get the models
        self.beam = self.sweep.get_beam()
        self.detector = self.sweep.get_detector()
        self.gonio = self.sweep.get_goniometer()
        assert (len(self.detector) == 1)

        # Get some stuff
        self.s0 = self.beam.get_s0()
        self.m2 = self.gonio.get_rotation_axis()
        self.image_size = self.detector[0].get_image_size()

        # Get a random s1/phi
        i = uniform(0, self.image_size[0])
        j = uniform(1, self.image_size[1])
        self.s1 = matrix.col(self.detector[0].get_pixel_lab_coord((i, j)))
        self.s1 = self.s1.normalize() * matrix.col(self.s0).length()
        self.phi = uniform(0, 5)
        self.x0 = int(floor(i - 10))
        self.y0 = int(floor(j - 10))

        # Set some parameters
        self.sigma_divergence = self.beam.get_sigma_divergence(deg=False)
        self.delta_divergence = 3 * self.sigma_divergence
        self.grid_half_size = 4
        self.step_size = (self.delta_divergence / self.grid_half_size,
                          self.delta_divergence / self.grid_half_size)

        # Create the coordinate system
        self.cs = CoordinateSystem(self.m2, self.s0, self.s1, self.phi)

        # Create the map of s1 coordinates
        self.s1_map = transform.beam_vector_map(self.detector[0], self.beam,
                                                True)

        # Create the grid index generator
        self.generate_indices = transform.GridIndexGenerator(
            self.cs, self.x0, self.y0, self.step_size, self.grid_half_size,
            self.s1_map)
Example #5
0
def compute_profile(experiments, reflection, reference, N):
    from dials.array_family import flex
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    from dials.algorithms.profile_model.modeller import GridSampler
    from dials_scratch.jmp.sim import compute_profile_internal
    from random import uniform

    sbox = reflection["shoebox"]
    bbox = sbox.bbox
    zs = sbox.zsize()
    ys = sbox.ysize()
    xs = sbox.xsize()

    profile = flex.double(flex.grid(zs, ys, xs))

    m2 = experiments[0].goniometer.get_rotation_axis_datum()
    s0 = experiments[0].beam.get_s0()
    s1 = reflection["s1"]
    phi = reflection["xyzcal.mm"][2]
    detector = experiments[0].detector
    scan = experiments[0].scan

    cs = CoordinateSystem(m2, s0, s1, phi)

    scan_range = scan.get_array_range()
    image_size = detector[0].get_image_size()
    grid_size = (3, 3, 40)
    assert grid_size[0] * grid_size[1] * grid_size[2] == len(reference[0])

    sampler = GridSampler(image_size, scan_range, grid_size)

    xyz = reflection["xyzcal.px"]
    index = sampler.nearest(0, xyz)

    for g in reference[0]:
        assert abs(flex.sum(g) - 1.0) < 1e-7

    grid = reference[0][index]

    sigma_d = experiments[0].profile.sigma_b(deg=False)
    sigma_m = experiments[0].profile.sigma_m(deg=False)
    delta_d = 3.0 * sigma_d
    delta_m = 3.0 * sigma_m

    profile = compute_profile_internal(grid, bbox, zs, ys, xs, N, delta_d,
                                       delta_m, detector, scan, cs)

    # from dials_scratch.jmp.viewer import show_image_stack_multi_view
    # show_image_stack_multi_view(profile.as_numpy_array(), vmax=max(profile))
    sum_p = flex.sum(profile)
    print("Partiality: %f" % sum_p)
    try:
        assert sum_p > 0, "sum_p == 0"
    except Exception as e:
        print(e)
        return None

    return profile
Example #6
0
def beamvector():
    """Initialise the transform"""

    bv = {
        "s0": (0.013141995425357206, 0.002199999234194632, 1.4504754950989514),
        "s1": (-0.01752795848400313, -0.24786554213968193, 1.4290948735525306),
        "m2": (0.999975, -0.001289, -0.006968),
        "phi": 5.83575672475 * math.pi / 180,
    }
    bv["cs"] = CoordinateSystem(bv["m2"], bv["s0"], bv["s1"], bv["phi"])
    return bv
Example #7
0
def xdscoordinates():
    """Initialise the coordinate system"""
    # Coordinate sensitive to length of vectors, so need to ensure that
    # lengths of both s0 and s1 are equal
    coords = {
        "s0": (0.013141995425357206, 0.002199999234194632, 1.4504754950989514),
        "s1": (-0.01752795848400313, -0.24786554213968193, 1.4290948735525306),
        "m2": (0.999975, -0.001289, -0.006968),
        "phi": 5.83575672475 * math.pi / 180,
    }
    coords["cs"] = CoordinateSystem(coords["m2"], coords["s0"], coords["s1"],
                                    coords["phi"])
    return coords
Example #8
0
def test_outer_bounds(setup):
    assert len(setup["detector"]) == 1
    s0 = setup["beam"].get_s0()
    m2 = setup["gonio"].get_rotation_axis()
    s0_length = matrix.col(setup["beam"].get_s0()).length()
    width, height = setup["detector"][0].get_image_size()
    zrange = setup["scan"].get_array_range()

    for i in range(1000):

        # Get random x, y, z
        x = random.uniform(0, 2000)
        y = random.uniform(0, 2000)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = (
            matrix.col(setup["detector"][0].get_pixel_lab_coord((x, y))).normalize()
            * s0_length
        )
        phi = setup["scan"].get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = setup["calculate_bbox"](s1, z, panel)
        z1, z2 = bbox[4], bbox[5]

        # Calculate the rotation angle for each point
        phi_dash1 = setup["scan"].get_angle_from_array_index(z1, deg=False)
        phi_dash2 = setup["scan"].get_angle_from_array_index(z2, deg=False)

        # Create the XDS coordinate system
        xcs = CoordinateSystem(m2, s0, s1, phi)

        # Calculate reciprocal space coordinates at each point
        e11, e21, e31 = xcs.from_beam_vector_and_rotation_angle(s1, phi_dash1)
        e12, e22, e32 = xcs.from_beam_vector_and_rotation_angle(s1, phi_dash2)

        # Check vertical edges
        for j in range(bbox[2], bbox[3] + 1):
            xyz1 = setup["detector"][0].get_pixel_lab_coord((bbox[0], j))
            xyz2 = setup["detector"][0].get_pixel_lab_coord((bbox[1] + 1, j))
            sdash1 = matrix.col(xyz1).normalize() * s0_length
            sdash2 = matrix.col(xyz2).normalize() * s0_length
            e11, e21, e3 = xcs.from_beam_vector_and_rotation_angle(sdash1, phi)
            e12, e22, e3 = xcs.from_beam_vector_and_rotation_angle(sdash2, phi)
            if bbox[0] > 0 and bbox[1] < width:
                assert (
                    abs(e11) >= setup["delta_divergence"]
                    or abs(e21) >= setup["delta_divergence"]
                )
                assert (
                    abs(e12) >= setup["delta_divergence"]
                    or abs(e22) >= setup["delta_divergence"]
                )

        # Check horizontal edges
        for i in range(bbox[0], bbox[1] + 1):
            xyz1 = setup["detector"][0].get_pixel_lab_coord((i, bbox[2]))
            xyz2 = setup["detector"][0].get_pixel_lab_coord((i, bbox[3] + 1))
            sdash1 = matrix.col(xyz1).normalize() * s0_length
            sdash2 = matrix.col(xyz2).normalize() * s0_length
            e11, e21, e3 = xcs.from_beam_vector_and_rotation_angle(sdash1, phi)
            e12, e22, e3 = xcs.from_beam_vector_and_rotation_angle(sdash2, phi)
            if bbox[2] > 0 and bbox[3] < height:
                assert (
                    abs(e11) >= setup["delta_divergence"]
                    or abs(e21) >= setup["delta_divergence"]
                )
                assert (
                    abs(e12) >= setup["delta_divergence"]
                    or abs(e22) >= setup["delta_divergence"]
                )

        # All e3 coords >= delta_mosaicity
        if bbox[4] > zrange[0] and bbox[5] < zrange[1]:
            assert abs(e31) >= setup["delta_mosaicity"]
            assert abs(e32) >= setup["delta_mosaicity"]
Example #9
0
def integrate_job(block,
                  experiments,
                  reflections,
                  reference,
                  grid_size=5,
                  detector_space=False):
    from dials.algorithms.profile_model.modeller import CircleSampler
    from dials.array_family import flex
    from dials.algorithms.profile_model.gaussian_rs.transform import TransformReverse
    from dials.algorithms.profile_model.gaussian_rs.transform import TransformForward
    from dials.algorithms.profile_model.gaussian_rs.transform import (
        TransformReverseNoModel, )
    from dials.algorithms.profile_model.gaussian_rs.transform import TransformSpec
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    from dials.algorithms.integration.fit import ProfileFitter
    from dials.array_family import flex
    from dials.model.data import make_image

    reflections["shoebox"] = flex.shoebox(reflections["panel"],
                                          reflections["bbox"],
                                          allocate=True)

    frame0, frame1 = experiments[0].scan.get_array_range()
    frame0 = frame0 + block[0]
    frame1 = frame0 + block[1]

    reflections["shoebox"] = flex.shoebox(reflections["panel"],
                                          reflections["bbox"],
                                          allocate=True)
    extractor = flex.ShoeboxExtractor(reflections, 1, frame0, frame1)

    iset = experiments[0].imageset[block[0]:block[1]]
    for i in range(len(iset)):
        print("Reading image %d" % i)
        data = iset.get_raw_data(i)
        mask = iset.get_mask(i)
        extractor.next(make_image(data, mask))

    print("Computing mask")
    reflections.compute_mask(experiments)

    print("Computing background")
    reflections.compute_background(experiments)

    print("Computing centroid")
    reflections.compute_centroid(experiments)

    print("Computing summed intensity")
    reflections.compute_summed_intensity()

    assert len(reference) % 9 == 0
    num_scan_points = len(reference) // 9

    sampler = CircleSampler(
        experiments[0].detector[0].get_image_size(),
        experiments[0].scan.get_array_range(),
        num_scan_points,
    )

    spec = TransformSpec(
        experiments[0].beam,
        experiments[0].detector,
        experiments[0].goniometer,
        experiments[0].scan,
        experiments[0].profile.sigma_b(deg=False),
        experiments[0].profile.sigma_m(deg=False),
        experiments[0].profile.n_sigma() * 1.5,
        grid_size,
    )

    m2 = experiments[0].goniometer.get_rotation_axis()
    s0 = experiments[0].beam.get_s0()

    Iprf = flex.double(len(reflections))
    Vprf = flex.double(len(reflections))
    Cprf = flex.double(len(reflections))
    Fprf = flex.bool(len(reflections))
    Part = reflections["partiality"]

    reflections["intensity.prf_old.value"] = reflections["intensity.prf.value"]
    reflections["intensity.prf_old.variance"] = reflections[
        "intensity.prf.variance"]

    selection = reflections.get_flags(reflections.flags.integrated_prf)

    reflections.unset_flags(~Fprf, reflections.flags.integrated_prf)

    for i, r in enumerate(reflections):

        if selection[i] == False:
            continue

        s1 = r["s1"]
        phi = r["xyzcal.mm"][2]
        xyz = r["xyzcal.px"]
        bbox = r["bbox"]
        panel = r["panel"]
        image = r["shoebox"].data.as_double()
        background = r["shoebox"].background.as_double()
        mask = r["shoebox"].mask.as_1d(
        ) == 5  # | (r['shoebox'].mask.as_1d() == 3)
        mask.reshape(image.accessor())
        cs = CoordinateSystem(m2, s0, s1, phi)

        index = sampler.nearest(0, xyz)

        profile, profile_mask = reference[index]

        # print flex.sum(profile)
        # print r['partiality']

        if detector_space:

            transform = TransformReverseNoModel(spec, cs, bbox, panel, profile)
            p = transform.profile()
            d = image
            m = mask
            b = background
            # print flex.sum(p)
            Part[i] = flex.sum(p)
            # ysize, xsize = p.all()[1:3]

            # p1 = flex.double(flex.grid(1, ysize , xsize))
            # d1 = flex.double(flex.grid(1, ysize , xsize))
            # b1 = flex.double(flex.grid(1, ysize , xsize))
            # m1 = flex.double(flex.grid(1, ysize , xsize))
            # for k in range(p.all()[0]):
            #   p1 += p[k:k+1,:,:]
            #   d1 += d[k:k+1,:,:]
            #   b1 += b[k:k+1,:,:]
            #   m1 = m[k:k+1,:,:]

            try:

                fit = ProfileFitter(d, b, m, p, 1e-3, 100)
                assert fit.niter() < 100
                Iprf[i] = fit.intensity()
                Vprf[i] = fit.variance()
                Cprf[i] = fit.correlation()
                Fprf[i] = True
                # if r['intensity.sum.value'] > 10 and abs(fit.intensity()) < 1e-3:
                print(
                    r["miller_index"],
                    i,
                    fit.intensity(),
                    r["intensity.sum.value"],
                    r["intensity.prf_old.value"],
                    Part[i],
                    fit.niter(),
                )
                # from matplotlib import pylab
                # pylab.imshow(p1.as_numpy_array()[0,:,:], interpolation='none')
                # pylab.show()
            except Exception as e:
                print(e)
                pass

        else:

            try:

                transform = TransformForward(spec, cs, bbox, panel, image,
                                             background, mask)

                p = profile
                d = transform.profile()
                b = transform.background()
                m = transform.mask() & profile_mask

                # if r['miller_index'] == (9, -25, 74):
                #   print list(p)
                #   print list(m)
                #   print list(b)
                #   print list(d)
                #   exit(0)

                fit = ProfileFitter(d, b, m, p, 1e-3, 100)
                assert fit.niter() < 100
                Iprf[i] = fit.intensity()[0]
                Vprf[i] = fit.variance()[0]
                Cprf[i] = fit.correlation()
                Fprf[i] = True
                print(r["miller_index"], i, fit.intensity(),
                      r["intensity.prf_old.value"])
                # from matplotlib import pylab
                # pylab.imshow(p1.as_numpy_array()[0,:,:], interpolation='none')
                # pylab.show()
            except Exception as e:
                pass

    reflections["intensity.prf.value"] = Iprf
    reflections["intensity.prf.variance"] = Vprf
    reflections["intensity.prf.correlation"] = Cprf
    reflections.set_flags(Fprf, reflections.flags.integrated_prf)

    del reflections["shoebox"]

    return reflections
Example #10
0
def compute_reference(experiments, reflections):
    from dials.algorithms.profile_model.modeller import CircleSampler
    from dials.array_family import flex
    from dials.algorithms.profile_model.gaussian_rs.transform import TransformForward
    from dials.algorithms.profile_model.gaussian_rs.transform import TransformSpec
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem

    reflections = select_strong(reflections)
    print("Selected %d strong spots" % len(reflections))

    sampler = CircleSampler(
        experiments[0].detector[0].get_image_size(),
        experiments[0].scan.get_array_range(),
        1,
    )

    n_sigma = 4.0
    grid_size = 25
    spec = TransformSpec(
        experiments[0].beam,
        experiments[0].detector,
        experiments[0].goniometer,
        experiments[0].scan,
        experiments[0].profile.sigma_b(deg=False),
        experiments[0].profile.sigma_m(deg=False),
        n_sigma,
        grid_size,
    )

    m2 = experiments[0].goniometer.get_rotation_axis()
    s0 = experiments[0].beam.get_s0()

    reference = [
        flex.double(
            flex.grid(1 + 2 * grid_size, 1 + 2 * grid_size, 1 + 2 * grid_size))
        for i in range(len(sampler))
    ]
    count = [0] * len(sampler)

    for r in reflections:
        s1 = r["s1"]
        phi = r["xyzcal.mm"][2]
        xyz = r["xyzcal.px"]
        bbox = r["bbox"]
        panel = r["panel"]
        image = r["shoebox"].data.as_double()
        mask = r["shoebox"].mask.as_1d() == 5
        mask.reshape(image.accessor())
        cs = CoordinateSystem(m2, s0, s1, phi)

        try:
            transform = TransformForward(spec, cs, bbox, panel, image, mask)
            d = transform.profile()

            d /= flex.sum(d)

            index = sampler.nearest(0, xyz)
            indices = sampler.nearest_n(0, xyz)
            for i in indices:
                w = sampler.weight(i, 0, xyz)
                reference[i] += w * d
                count[i] += 1
        except Exception:
            pass

    for i in range(len(reference)):
        r = reference[i]
        if flex.sum(r) > 0:
            print(flex.max(r))
            g = r.accessor()
            r = r.as_1d()
            s = r > 0.02 * flex.max(r)
            r.set_selected(~s, flex.double(len(r), 0))
            r = r / flex.sum(r)
            r.reshape(g)
            reference[i] = r

    for i in range(len(reference)):
        from matplotlib import pylab

        print(count[i])
        r = reference[i]
        d = r.as_numpy_array()[11, :, :]
        pylab.imshow(d, interpolation="None")
        pylab.show()

    return reference
Example #11
0
  def tst_outer_bounds(self):

    from scitbx import matrix
    from random import uniform
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem

    assert(len(self.detector) == 1)
    s0 = self.beam.get_s0()
    m2 = self.gonio.get_rotation_axis()
    s0_length = matrix.col(self.beam.get_s0()).length()
    width, height = self.detector[0].get_image_size()
    zrange = self.scan.get_array_range()

    for i in range(1000):

      # Get random x, y, z
      x = uniform(0, 2000)
      y = uniform(0, 2000)
      z = uniform(0, 9)

      # Get random s1, phi, panel
      s1 = matrix.col(self.detector[0].get_pixel_lab_coord(
          (x, y))).normalize() * s0_length
      phi = self.scan.get_angle_from_array_index(z, deg=False)
      panel = 0

      # Calculate the bounding box
      bbox = self.calculate_bbox(s1, z, panel)
      x1, x2 = bbox[0], bbox[1]
      y1, y2 = bbox[2], bbox[3]
      z1, z2 = bbox[4], bbox[5]

      # Calculate the rotation angle for each point
      phi_dash1 = self.scan.get_angle_from_array_index(z1, deg = False)
      phi_dash2 = self.scan.get_angle_from_array_index(z2, deg = False)

      # Create the XDS coordinate system
      xcs = CoordinateSystem(m2, s0, s1, phi)

      # Calculate reciprocal space coordinates at each point
      e11, e21, e31 = xcs.from_beam_vector_and_rotation_angle(s1, phi_dash1)
      e12, e22, e32 = xcs.from_beam_vector_and_rotation_angle(s1, phi_dash2)

      # Check vertical edges
      for j in range(bbox[2], bbox[3] + 1):
        xyz1 = self.detector[0].get_pixel_lab_coord((bbox[0], j))
        xyz2 = self.detector[0].get_pixel_lab_coord((bbox[1] + 1, j))
        sdash1 = matrix.col(xyz1).normalize() * s0_length
        sdash2 = matrix.col(xyz2).normalize() * s0_length
        e11, e21, e3 = xcs.from_beam_vector_and_rotation_angle(sdash1, phi)
        e12, e22, e3 = xcs.from_beam_vector_and_rotation_angle(sdash2, phi)
        if bbox[0] > 0 and bbox[1] < width:
          assert(abs(e11) >= self.delta_divergence or
                 abs(e21) >= self.delta_divergence)
          assert(abs(e12) >= self.delta_divergence or
                 abs(e22) >= self.delta_divergence)

      # Check horizontal edges
      for i in range(bbox[0], bbox[1] + 1):
        xyz1 = self.detector[0].get_pixel_lab_coord((i, bbox[2]))
        xyz2 = self.detector[0].get_pixel_lab_coord((i, bbox[3] + 1))
        sdash1 = matrix.col(xyz1).normalize() * s0_length
        sdash2 = matrix.col(xyz2).normalize() * s0_length
        e11, e21, e3 = xcs.from_beam_vector_and_rotation_angle(sdash1, phi)
        e12, e22, e3 = xcs.from_beam_vector_and_rotation_angle(sdash2, phi)
        if bbox[2] > 0 and bbox[3] < height:
          assert(abs(e11) >= self.delta_divergence or
                 abs(e21) >= self.delta_divergence)
          assert(abs(e12) >= self.delta_divergence or
                 abs(e22) >= self.delta_divergence)

      # All e3 coords >= delta_mosaicity
      if bbox[4] > zrange[0] and bbox[5] < zrange[1]:
        assert(abs(e31) >= self.delta_mosaicity)
        assert(abs(e32) >= self.delta_mosaicity)

    print 'OK'
Example #12
0
def test(dials_data):
    experiment = ExperimentList.from_file(
        dials_data("centroid_test_data").join("experiments.json"))

    beam = experiment[0].beam
    detector = experiment[0].detector
    goniometer = experiment[0].goniometer
    scan = experiment[0].scan
    delta_b = experiment[0].profile.delta_b()
    delta_m = experiment[0].profile.delta_m()

    assert len(detector) == 1

    # Get the function object to mask the foreground
    mask_foreground = MaskCalculator3D(beam, detector, goniometer, scan,
                                       delta_b, delta_m)

    s0 = beam.get_s0()
    m2 = goniometer.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()
    width, height = detector[0].get_image_size()
    zrange = scan.get_array_range()
    phi0, dphi = scan.get_oscillation(deg=False)

    # Generate some reflections
    reflections = generate_reflections(detector, beam, scan, experiment, 10)

    # Mask the foreground in each
    mask_foreground(
        reflections["shoebox"],
        reflections["s1"],
        reflections["xyzcal.px"].parts()[2],
        reflections["panel"],
    )

    # Loop through all the reflections and check the mask values
    shoebox = reflections["shoebox"]
    beam_vector = reflections["s1"]
    rotation_angle = reflections["xyzcal.mm"].parts()[2]
    for l in range(len(reflections)):
        mask = shoebox[l].mask
        x0, x1, y0, y1, z0, z1 = shoebox[l].bbox
        s1 = beam_vector[l]
        phi = rotation_angle[l]
        cs = CoordinateSystem(m2, s0, s1, phi)

        def rs_coord(i, j, k):
            s1d = detector[0].get_pixel_lab_coord((i, j))
            s1d = matrix.col(s1d).normalize() * s0_length
            e1, e2 = cs.from_beam_vector(s1d)
            e3 = cs.from_rotation_angle_fast(phi0 + (k - zrange[0]) * dphi)
            return e1, e2, e3

        new_mask = flex.int(mask.accessor(), 0)
        for k in range(z1 - z0):
            for j in range(y1 - y0):
                for i in range(x1 - x0):
                    # value1 = mask[k, j, i]
                    e11, e12, e13 = rs_coord(x0 + i, y0 + j, z0 + k)
                    e21, e22, e23 = rs_coord(x0 + i + 1, y0 + j, z0 + k)
                    e31, e32, e33 = rs_coord(x0 + i, y0 + j + 1, z0 + k)
                    e41, e42, e43 = rs_coord(x0 + i, y0 + j, z0 + k + 1)
                    e51, e52, e53 = rs_coord(x0 + i + 1, y0 + j + 1, z0 + k)
                    e61, e62, e63 = rs_coord(x0 + i + 1, y0 + j, z0 + k + 1)
                    e71, e72, e73 = rs_coord(x0 + i, y0 + j + 1, z0 + k + 1)
                    e81, e82, e83 = rs_coord(x0 + i + 1, y0 + j + 1,
                                             z0 + k + 1)
                    de1 = (e11 / delta_b)**2 + (
                        e12 / delta_b)**2  # +(e13/delta_m)**2
                    de2 = (e21 / delta_b)**2 + (
                        e22 / delta_b)**2  # +(e23/delta_m)**2
                    de3 = (e31 / delta_b)**2 + (
                        e32 / delta_b)**2  # +(e33/delta_m)**2
                    de4 = (e41 / delta_b)**2 + (
                        e42 / delta_b)**2  # +(e43/delta_m)**2
                    de5 = (e51 / delta_b)**2 + (
                        e52 / delta_b)**2  # +(e53/delta_m)**2
                    de6 = (e61 / delta_b)**2 + (
                        e62 / delta_b)**2  # +(e63/delta_m)**2
                    de7 = (e71 / delta_b)**2 + (
                        e72 / delta_b)**2  # +(e73/delta_m)**2
                    de8 = (e81 / delta_b)**2 + (
                        e82 / delta_b)**2  # +(e83/delta_m)**2
                    de = math.sqrt(
                        min([de1, de2, de3, de4, de5, de6, de7, de8]))
                    if (x0 + i < 0 or y0 + j < 0 or x0 + i >= width
                            or y0 + j >= height or z0 + k < zrange[0]
                            or z0 + k >= zrange[1]):
                        value2 = MaskCode.Valid
                    else:
                        if de <= 1.0:
                            value2 = MaskCode.Valid | MaskCode.Foreground
                        else:
                            value2 = MaskCode.Valid | MaskCode.Background
                    new_mask[k, j, i] = value2

        if not all(m1 == m2 for m1, m2 in zip(mask, new_mask)):
            np.set_printoptions(threshold=10000)
            diff = (mask == new_mask).as_numpy_array()
            print(diff.astype(int))
            # print mask.as_numpy_array()
            # print new_mask.as_numpy_array()
            # print (new_mask.as_numpy_array()[:,:,:] %2) * (new_mask.as_numpy_array() == 5)
            assert False
Example #13
0
def test_run(dials_data):
    from dials.algorithms.profile_model.gaussian_rs import transform
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    from scitbx import matrix
    from dials.model.serialize import load

    sequence = load.sequence(
        dials_data("centroid_test_data").join("sweep.json").strpath)

    # Get the models
    beam = sequence.get_beam()
    detector = sequence.get_detector()
    gonio = sequence.get_goniometer()
    assert len(detector) == 1

    # Get some stuff
    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    image_size = detector[0].get_image_size()

    # Get a random s1/phi
    i = random.uniform(0, image_size[0])
    j = random.uniform(1, image_size[1])
    s1 = matrix.col(detector[0].get_pixel_lab_coord((i, j)))
    s1 = s1.normalize() * matrix.col(s0).length()
    phi = random.uniform(0, 5)
    x0 = int(math.floor(i - 10))
    y0 = int(math.floor(j - 10))

    # Set some parameters
    sigma_divergence = beam.get_sigma_divergence(deg=False)
    delta_divergence = 3 * sigma_divergence
    grid_half_size = 4
    step_size = (delta_divergence / grid_half_size,
                 delta_divergence / grid_half_size)

    # Create the coordinate system
    cs = CoordinateSystem(m2, s0, s1, phi)

    # Create the map of s1 coordinates
    s1_map = transform.beam_vector_map(detector[0], beam, True)

    # Create the grid index generator
    generate_indices = transform.GridIndexGenerator(cs, x0, y0, step_size,
                                                    grid_half_size, s1_map)

    for j in range(0, 20):
        for i in range(0, 20):

            xx = x0 + i
            yy = y0 + j
            if xx < 0 or yy < 0 or xx >= image_size[0] or yy >= image_size[0]:
                continue

            # Get the grid indices
            gi_1, gj_1 = generate_indices(j, i)

            # Get the grid indices
            xyz = matrix.col(detector[0].get_pixel_lab_coord((x0 + i, y0 + j)))
            xyz = xyz.normalize() * matrix.col(s0).length()
            c1, c2 = matrix.col(cs.from_beam_vector(xyz))
            gi_2 = grid_half_size + c1 / step_size[0] + 0.5
            gj_2 = grid_half_size + c2 / step_size[1] + 0.5

            # Check both are the same
            eps = 1e-7
            assert abs(gj_1 - gj_2) <= eps, (gi_1, gi_2, gj_1, gj_2)
            assert abs(gi_1 - gi_2) <= eps, (gi_1, gi_2, gj_1, gj_2)
Example #14
0
def test_forward_no_model(dials_data):
    sequence = load.imageset(
        dials_data("centroid_test_data").join("sweep.json").strpath)

    # Get the models
    beam = sequence.get_beam()
    detector = sequence.get_detector()
    gonio = sequence.get_goniometer()
    scan = sequence.get_scan()
    scan.set_image_range((0, 1000))

    # Set some parameters
    sigma_divergence = beam.get_sigma_divergence(deg=False)
    mosaicity = 0.157 * math.pi / 180
    n_sigma = 3
    grid_size = 20
    delta_divergence = n_sigma * sigma_divergence

    step_size = delta_divergence / grid_size
    delta_divergence2 = delta_divergence + step_size * 0.5
    delta_mosaicity = n_sigma * mosaicity

    # Create the bounding box calculator
    calculate_bbox = BBoxCalculator3D(beam, detector, gonio, scan,
                                      delta_divergence2, delta_mosaicity)

    # Initialise the transform
    spec = transform.TransformSpec(beam, detector, gonio, scan,
                                   sigma_divergence, mosaicity, n_sigma + 1,
                                   grid_size)

    # tst_conservation_of_counts(self):

    random.seed(0)

    assert len(detector) == 1

    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    # Create an s1 map
    s1_map = transform.beam_vector_map(detector[0], beam, True)

    for i in range(100):

        # Get random x, y, z
        x = random.uniform(300, 1800)
        y = random.uniform(300, 1800)
        z = random.uniform(500, 600)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, z, panel)
        x0, x1, y0, y1, z0, z1 = bbox

        # Create the coordinate system
        cs = CoordinateSystem(m2, s0, s1, phi)
        if abs(cs.zeta()) < 0.1:
            continue

        # The grid index generator
        step_size = delta_divergence / grid_size
        grid_index = transform.GridIndexGenerator(cs, x0, y0,
                                                  (step_size, step_size),
                                                  grid_size, s1_map)

        # Create the image
        # image = flex.double(flex.grid(z1 - z0, y1 - y0, x1 - x0), 1)
        image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
                         (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))
        mask = flex.bool(flex.grid(image.all()), False)
        for j in range(y1 - y0):
            for i in range(x1 - x0):
                inside = False
                gx00, gy00 = grid_index(j, i)
                gx01, gy01 = grid_index(j, i + 1)
                gx10, gy10 = grid_index(j + 1, i)
                gx11, gy11 = grid_index(j + 1, i + 1)
                mingx = min([gx00, gx01, gx10, gx11])
                maxgx = max([gx00, gx01, gx10, gx11])
                mingy = min([gy00, gy01, gy10, gy11])
                maxgy = max([gy00, gy01, gy10, gy11])
                if (mingx >= 0 and maxgx < 2 * grid_size + 1 and mingy >= 0
                        and maxgy < 2 * grid_size + 1):
                    inside = True
                for k in range(1, z1 - z0 - 1):
                    mask[k, j, i] = inside

        # Transform the image to the grid
        transformed = transform.TransformForwardNoModel(
            spec, cs, bbox, 0, image.as_double(), mask)
        grid = transformed.profile()

        # Get the sums and ensure they're the same
        eps = 1e-7
        sum_grid = flex.sum(grid)
        sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
        assert abs(sum_grid - sum_image) <= eps

        mask = flex.bool(flex.grid(image.all()), True)
        transformed = transform.TransformForwardNoModel(
            spec, cs, bbox, 0, image.as_double(), mask)
        grid = transformed.profile()

        # Boost the bbox to make sure all intensity is included
        x0, x1, y0, y1, z0, z1 = bbox
        bbox2 = (x0 - 10, x1 + 10, y0 - 10, y1 + 10, z0 - 10, z1 + 10)

        # Do the reverse transform
        transformed = transform.TransformReverseNoModel(
            spec, cs, bbox2, 0, grid)
        image2 = transformed.profile()

        # Check the sum of pixels are the same
        sum_grid = flex.sum(grid)
        sum_image = flex.sum(image2)
        assert abs(sum_grid - sum_image) <= eps

        # Do the reverse transform
        transformed = transform.TransformReverseNoModel(
            spec, cs, bbox, 0, grid)
        image2 = transformed.profile()

        from dials.algorithms.statistics import pearson_correlation_coefficient

        cc = pearson_correlation_coefficient(image.as_1d().as_double(),
                                             image2.as_1d())
        assert cc >= 0.99
Example #15
0
    def __call__(self):

        from scitbx import matrix
        from random import uniform
        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
        from scitbx.array_family import flex
        assert (len(self.detector) == 1)
        s0 = self.beam.get_s0()
        m2 = self.gonio.get_rotation_axis()
        s0_length = matrix.col(self.beam.get_s0()).length()

        for i in range(100):

            # Get random x, y, z
            x = uniform(0, 2000)
            y = uniform(0, 2000)
            z = uniform(0, 9)

            # Get random s1, phi, panel
            s1 = matrix.col(self.detector[0].get_pixel_lab_coord(
                (x, y))).normalize() * s0_length
            phi = self.scan.get_angle_from_array_index(z, deg=False)
            panel = 0

            # Calculate the bounding box
            bbox = self.calculate_bbox(s1, z, panel)
            x1, x2 = bbox[0], bbox[1]
            y1, y2 = bbox[2], bbox[3]
            z1, z2 = bbox[4], bbox[5]

            # Create the XDS coordinate system
            xcs = CoordinateSystem(m2, s0, s1, phi)

            # Calculate the transform fraction
            fraction = self.transform(bbox[4:], phi, xcs.zeta())

            # Ensure the minimum and maximum are 0 < 1
            fmax = flex.max(fraction)
            fmin = flex.min(fraction)
            assert (fmax <= (1.0 + 5e-15)
                    and fmax > 0.0), "%.16f not between 0 and 1" % fmax
            assert (fmin >= 0.0 and fmin <= 1.0)

            # Ensure the fraction for each image frame adds up to 1.0 for
            # all those frames completely within the grid
            for j in range(1, fraction.all()[0] - 1):
                tot = flex.sum(fraction[j:j + 1, :])
                assert (abs(tot - 1.0) < 1e-7)

            # Ensure the frames follow a progression through the grid. I.e,
            # check that values increase then decrease and don't jump around
            for j in range(fraction.all()[0]):
                f = fraction[j:j + 1, :]
                last = f[0]
                rev = False
                for i in range(1, len(f)):
                    curr = f[1]
                    if rev == False:
                        if curr < last:
                            rev = True
                    else:
                        assert (curr <= last)
                    last = curr

        # Test passed
        print 'OK'
Example #16
0
  def __call__(self):

    from scitbx import matrix
    from random import uniform
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    from scitbx.array_family import flex
    assert(len(self.detector) == 1)
    s0 = self.beam.get_s0()
    m2 = self.gonio.get_rotation_axis()
    s0_length = matrix.col(self.beam.get_s0()).length()

    for i in range(100):

      # Get random x, y, z
      x = uniform(0, 2000)
      y = uniform(0, 2000)
      z = uniform(0, 9)

      # Get random s1, phi, panel
      s1 = matrix.col(self.detector[0].get_pixel_lab_coord(
          (x, y))).normalize() * s0_length
      phi = self.scan.get_angle_from_array_index(z, deg=False)
      panel = 0

      # Calculate the bounding box
      bbox = self.calculate_bbox(s1, z, panel)
      x1, x2 = bbox[0], bbox[1]
      y1, y2 = bbox[2], bbox[3]
      z1, z2 = bbox[4], bbox[5]

      # Create the XDS coordinate system
      xcs = CoordinateSystem(m2, s0, s1, phi)

      # Calculate the transform fraction
      fraction = self.transform(bbox[4:], phi, xcs.zeta())

      # Ensure the minimum and maximum are 0 < 1
      fmax = flex.max(fraction)
      fmin = flex.min(fraction)
      assert(fmax <= (1.0 + 5e-15) and fmax > 0.0), "%.16f not between 0 and 1" % fmax
      assert(fmin >= 0.0 and fmin <= 1.0)

      # Ensure the fraction for each image frame adds up to 1.0 for
      # all those frames completely within the grid
      for j in range(1, fraction.all()[0]-1):
        tot = flex.sum(fraction[j:j+1,:])
        assert(abs(tot - 1.0) < 1e-7)

      # Ensure the frames follow a progression through the grid. I.e,
      # check that values increase then decrease and don't jump around
      for j in range(fraction.all()[0]):
        f = fraction[j:j+1,:]
        last = f[0]
        rev = False
        for i in range(1,len(f)):
          curr = f[1]
          if rev == False:
            if curr < last:
              rev = True
          else:
            assert(curr <= last)
          last = curr

    # Test passed
    print 'OK'
Example #17
0
def test_forward_panel_edge(dials_data):
    expt = ExperimentList.from_file(
        dials_data("centroid_test_data").join(
            "imported_experiments.json").strpath)[0]

    # Get the models
    beam = expt.beam
    detector = expt.detector
    gonio = expt.goniometer
    scan = expt.scan

    # Set some parameters
    sigma_divergence = 0.00101229
    mosaicity = 0.157 * math.pi / 180
    n_sigma = 3
    grid_size = 7
    delta_divergence = n_sigma * sigma_divergence

    step_size = delta_divergence / grid_size
    delta_divergence2 = delta_divergence + step_size * 0.5
    delta_mosaicity = n_sigma * mosaicity

    # Create the bounding box calculator
    calculate_bbox = BBoxCalculator3D(beam, detector, gonio, scan,
                                      delta_divergence2, delta_mosaicity)

    # Initialise the transform
    spec = transform.TransformSpec(beam, detector, gonio, scan,
                                   sigma_divergence, mosaicity, n_sigma + 1,
                                   grid_size)

    assert len(detector) == 1

    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    image_size = detector[0].get_image_size()
    refl_xy = [
        (0, 0),
        (2, 3),
        (4, 1000),
        (1000, 5),
        (image_size[0] - 1, image_size[1] - 1),
        (image_size[0] - 2, 1),
        (1, image_size[1] - 5),
        (1000, image_size[1] - 4),
        (image_size[0] - 3, 1000),
    ]

    for x, y in refl_xy:
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, z, panel)
        x0, x1, y0, y1, z0, z1 = bbox

        # Create the coordinate system
        cs = CoordinateSystem(m2, s0, s1, phi)

        # Create the image
        image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
                         (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))

        # Mask for the foreground pixels
        refl_mask = image > 1e-3
        bg = flex.double(image.accessor())

        # Shoebox mask, i.e. mask out pixels that are outside the panel bounds
        shoebox_mask = flex.bool(image.accessor(), False)
        for j in range(y1 - y0):
            for i in range(x1 - x0):
                if (j + y0 >= 0 and j + y0 < image_size[1] and i + x0 >= 0
                        and i + x0 < image_size[0]):
                    for k in range(z1 - z0):
                        shoebox_mask[k, j, i] = True

        mask = refl_mask & shoebox_mask

        # from matplotlib import pyplot as plt
        # fig, axes = plt.subplots(ncols=refl_mask.focus()[0], nrows=4)
        # for i in range(refl_mask.focus()[0]):
        # axes[0, i].imshow(image.as_numpy_array()[i])
        # axes[1, i].imshow(refl_mask.as_numpy_array()[i])
        # axes[2, i].imshow(shoebox_mask.as_numpy_array()[i])
        # axes[3, i].imshow(mask.as_numpy_array()[i])
        # plt.show()

        # Transform the image to the grid
        transformed = transform.TransformForward(spec, cs, bbox, 0,
                                                 image.as_double(), bg,
                                                 refl_mask)
        grid = transformed.profile()

        mask = refl_mask & shoebox_mask
        # assert only pixels within the panel were transformed
        assert flex.sum(grid) == pytest.approx(flex.sum(
            image.select(mask.as_1d())),
                                               rel=0.01)
        # The total transformed counts should be less than the (unmasked) image counts
        assert flex.sum(grid) < flex.sum(image)

        # Transform the image to the grid, this time without a background
        transformed = transform.TransformForward(spec, cs, bbox, 0,
                                                 image.as_double(), refl_mask)
        grid = transformed.profile()

        mask = refl_mask & shoebox_mask
        # assert only pixels within the panel were transformed
        assert flex.sum(grid) == pytest.approx(flex.sum(
            image.select(mask.as_1d())),
                                               rel=0.01)
        # The total transformed counts should be less than the (unmasked) image counts
        assert flex.sum(grid) < flex.sum(image)
Example #18
0
def test_forward(dials_data):
    from dials.model.serialize import load
    from dials.algorithms.profile_model.gaussian_rs import transform
    from dials.algorithms.profile_model.gaussian_rs import BBoxCalculator3D

    sweep = load.sweep(
        dials_data("centroid_test_data").join("sweep.json").strpath)

    # Get the models
    beam = sweep.get_beam()
    detector = sweep.get_detector()
    gonio = sweep.get_goniometer()
    scan = sweep.get_scan()

    #        beam.set_direction((0.0, 0.0, 1.0))
    #        gonio.set_rotation_axis((1.0, 0.0, 0.0))
    #        detector.set_frame((1.0, 0.0, 0.0),
    #                                (0.0, 1.0, 0.0),
    #                                (-150, -150, -200))

    # Set some parameters
    sigma_divergence = beam.get_sigma_divergence(deg=False)
    mosaicity = 0.157 * math.pi / 180
    n_sigma = 3
    grid_size = 7
    delta_divergence = n_sigma * sigma_divergence

    step_size = delta_divergence / grid_size
    delta_divergence2 = delta_divergence + step_size * 0.5
    delta_mosaicity = n_sigma * mosaicity

    # Create the bounding box calculator
    calculate_bbox = BBoxCalculator3D(beam, detector, gonio, scan,
                                      delta_divergence2, delta_mosaicity)

    # Initialise the transform
    spec = transform.TransformSpec(beam, detector, gonio, scan,
                                   sigma_divergence, mosaicity, n_sigma + 1,
                                   grid_size)

    # tst_conservation_of_counts(self):

    from scitbx import matrix
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    from dials.algorithms.profile_model.gaussian_rs import transform
    from scitbx.array_family import flex

    assert len(detector) == 1

    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    # Create an s1 map
    s1_map = transform.beam_vector_map(detector[0], beam, True)

    for i in range(100):

        # Get random x, y, z
        x = random.uniform(300, 1800)
        y = random.uniform(300, 1800)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, z, panel)
        x0, x1, y0, y1, z0, z1 = bbox

        # Create the coordinate system
        cs = CoordinateSystem(m2, s0, s1, phi)

        # The grid index generator
        step_size = delta_divergence / grid_size
        grid_index = transform.GridIndexGenerator(cs, x0, y0,
                                                  (step_size, step_size),
                                                  grid_size, s1_map)

        # Create the image
        # image = flex.double(flex.grid(z1 - z0, y1 - y0, x1 - x0), 1)
        image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
                         (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))
        mask = flex.bool(flex.grid(image.all()), False)
        for j in range(y1 - y0):
            for i in range(x1 - x0):
                inside = False
                gx00, gy00 = grid_index(j, i)
                gx01, gy01 = grid_index(j, i + 1)
                gx10, gy10 = grid_index(j + 1, i)
                gx11, gy11 = grid_index(j + 1, i + 1)
                mingx = min([gx00, gx01, gx10, gx11])
                maxgx = max([gx00, gx01, gx10, gx11])
                mingy = min([gy00, gy01, gy10, gy11])
                maxgy = max([gy00, gy01, gy10, gy11])
                if (mingx >= 0 and maxgx < 2 * grid_size + 1 and mingy >= 0
                        and maxgy < 2 * grid_size + 1):
                    inside = True
                for k in range(1, z1 - z0 - 1):
                    mask[k, j, i] = inside

        # Transform the image to the grid
        transformed = transform.TransformForward(spec, cs, bbox, 0,
                                                 image.as_double(), mask)
        grid = transformed.profile()

        # Get the sums and ensure they're the same
        eps = 1e-7
        sum_grid = flex.sum(grid)
        sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
        assert abs(sum_grid - sum_image) <= eps

    # Test passed

    #    def tst_transformed_centroid(self):

    #        from scitbx import matrix
    #        from random import uniform
    #        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    #        from dials.algorithms.profile_model.gaussian_rs import transform
    #        from scitbx.array_family import flex
    #        from time import time

    #        s0 = beam.get_s0()
    #        m2 = gonio.get_rotation_axis()
    #        s0_length = matrix.col(beam.get_s0()).length()

    #        # Create an s1 map
    #        s1_map = transform.beam_vector_map(detector, beam, True)

    #        # Get random x, y, z
    #        x = random.uniform(300, 1800)
    #        y = random.uniform(300, 1800)
    #        z = random.uniform(-10, 0)

    #        # Get random s1, phi, panel
    #        s1 = matrix.col(detector.get_pixel_lab_coord(
    #            (x, y))).normalize() * s0_length
    #        phi = scan.get_angle_from_array_index(z, deg=False)
    #        panel = 0

    #        # Calculate the bounding box
    #        bbox = calculate_bbox(s1, z, panel)
    #        x0, x1, y0, y1, z0, z1 = bbox

    #        # Create the coordinate system
    #        cs = CoordinateSystem(m2, s0, s1, phi)

    #        # The grid index generator
    #        step_size = delta_divergence / grid_size
    #        grid_index = transform.GridIndexGenerator(cs, x0, y0,
    #            (step_size, step_size), grid_size, s1_map)

    #        # Create the image
    #        image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
    #            (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))

    #        print x, y, z, bbox
    #        print (z1 - z0, y1 - y0, x1 - x0), (z - z0, y - y0, x - x0)

    #        mask = flex.bool(flex.grid(image.all()), False)
    #        for j in range(y1 - y0):
    #            for i in range(x1 - x0):
    #                inside = False
    #                gx00, gy00 = grid_index(j, i)
    #                gx01, gy01 = grid_index(j, i+1)
    #                gx10, gy10 = grid_index(j+1, i)
    #                gx11, gy11 = grid_index(j+1, i+1)
    #                mingx = min([gx00, gx01, gx10, gx11])
    #                maxgx = max([gx00, gx01, gx10, gx11])
    #                mingy = min([gy00, gy01, gy10, gy11])
    #                maxgy = max([gy00, gy01, gy10, gy11])
    #                if (mingx >= 0 and maxgx <= 2 * grid_size + 1 and
    #                    mingy >= 0 and maxgy <= 2 * grid_size + 1):
    #                    inside = True
    #                for k in range(1, z1 - z0 - 1):
    #                    mask[k,j,i] = inside
    #                    #image[k,j,i] *= inside
    #        from matplotlib import pylab
    #        pylab.imshow(image.as_numpy_array()[(z1 - z0) / 2,:,:], interpolation='none')
    #        pylab.show()

    #        # Transform the image to the grid
    #        grid = transform(cs, bbox, image, mask)

    #        from matplotlib import pylab
    #        pylab.imshow(grid.as_numpy_array()[7,:,:], interpolation='none')
    #        pylab.show()

    #        # Get the sums and ensure they're the same
    #        eps = 1e-7
    #        sum_grid = flex.sum(grid)
    #        sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
    #        assert(abs(sum_grid - sum_image) <= eps)

    #        # Check the centroid
    #        sz = grid_size * 2 + 1
    #        grid_x = flex.double(flex.grid(sz, sz, sz))
    #        grid_y = flex.double(flex.grid(sz, sz, sz))
    #        grid_z = flex.double(flex.grid(sz, sz, sz))
    #        for k in range(sz):
    #            for j in range(sz):
    #                for i in range(sz):
    #                    grid_x[k,j,i] = i + 0.5
    #                    grid_y[k,j,i] = j + 0.5
    #                    grid_z[k,j,i] = k + 0.5
    #
    #        sum_grid_x = flex.sum(grid * grid_x)
    #        sum_grid_y = flex.sum(grid * grid_y)
    #        sum_grid_z = flex.sum(grid * grid_z)
    #        xc = sum_grid_x / sum_grid
    #        yc = sum_grid_y / sum_grid
    #        zc = sum_grid_z / sum_grid
    #        print xc, yc, zc
    #        assert(abs(xc - grid_size + 0.5) <= 0.5)
    #        assert(abs(yc - grid_size + 0.5) <= 0.5)
    #        assert(abs(zc - grid_size + 0.5) <= 0.5)

    #        # Test passed
    #        print 'OK'

    # tst_transform_with_background(self):

    from scitbx import matrix
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    from dials.algorithms.profile_model.gaussian_rs import transform
    from scitbx.array_family import flex

    assert len(detector) == 1
    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    # Create an s1 map
    s1_map = transform.beam_vector_map(detector[0], beam, True)

    for i in range(100):

        # Get random x, y, z
        x = random.uniform(300, 1800)
        y = random.uniform(300, 1800)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, z, panel)
        x0, x1, y0, y1, z0, z1 = bbox

        # Create the coordinate system
        cs = CoordinateSystem(m2, s0, s1, phi)

        # The grid index generator
        step_size = delta_divergence / grid_size
        grid_index = transform.GridIndexGenerator(cs, x0, y0,
                                                  (step_size, step_size),
                                                  grid_size, s1_map)

        # Create the image
        # image = flex.double(flex.grid(z1 - z0, y1 - y0, x1 - x0), 1)
        image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
                         (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))
        background = flex.random_double(len(image))
        background.resize(image.accessor())
        mask = flex.bool(flex.grid(image.all()), False)
        for j in range(y1 - y0):
            for i in range(x1 - x0):
                inside = False
                gx00, gy00 = grid_index(j, i)
                gx01, gy01 = grid_index(j, i + 1)
                gx10, gy10 = grid_index(j + 1, i)
                gx11, gy11 = grid_index(j + 1, i + 1)
                mingx = min([gx00, gx01, gx10, gx11])
                maxgx = max([gx00, gx01, gx10, gx11])
                mingy = min([gy00, gy01, gy10, gy11])
                maxgy = max([gy00, gy01, gy10, gy11])
                if (mingx >= 0 and maxgx <= 2 * grid_size + 1 and mingy >= 0
                        and maxgy <= 2 * grid_size + 1):
                    inside = True
                for k in range(1, z1 - z0 - 1):
                    mask[k, j, i] = inside

        # Transform the image to the grid
        transformed = transform.TransformForward(spec, cs, bbox, 0,
                                                 image.as_double(),
                                                 background.as_double(), mask)
        igrid = transformed.profile()
        bgrid = transformed.background()

        # Get the sums and ensure they're the same
        eps = 1e-7
        sum_igrid = flex.sum(igrid)
        sum_bgrid = flex.sum(bgrid)
        sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
        sum_bkgrd = flex.sum(flex.double(flex.select(background, flags=mask)))
        try:
            assert abs(sum_igrid - sum_image) <= eps
            assert abs(sum_bgrid - sum_bkgrd) <= eps
        except Exception:
            print("Failed for: ", (x, y, z))
            raise
Example #19
0
def test_map_frames_forward(dials_data):
    sequence = load.imageset(
        dials_data("centroid_test_data").join("sweep.json").strpath)

    # Get the models
    beam = sequence.get_beam()
    detector = sequence.get_detector()
    gonio = sequence.get_goniometer()
    scan = sequence.get_scan()

    # Set the delta_divergence/mosaicity
    n_sigma = 3
    sigma_divergence = 0.060 * math.pi / 180
    mosaicity = 0.154 * math.pi / 180
    delta_divergence = n_sigma * sigma_divergence
    delta_mosaicity = n_sigma * mosaicity

    # Set the grid size
    grid_size = (4, 4, 4)

    # Create the E3 fraction object
    transform = MapFramesForward(
        scan.get_array_range()[0],
        scan.get_oscillation(deg=False)[0],
        scan.get_oscillation(deg=False)[1],
        mosaicity,
        n_sigma,
        grid_size[2],
    )

    # Create the bounding box calculator
    calculate_bbox = BBoxCalculator3D(beam, detector, gonio, scan,
                                      delta_divergence, delta_mosaicity)

    assert len(detector) == 1
    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    for i in range(100):

        # Get random x, y, z
        x = random.uniform(0, 2000)
        y = random.uniform(0, 2000)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, z, panel)

        # Create the XDS coordinate system
        xcs = CoordinateSystem(m2, s0, s1, phi)

        # Calculate the transform fraction
        fraction = transform(bbox[4:], phi, xcs.zeta())

        # Ensure the minimum and maximum are 0 < 1
        fmax = flex.max(fraction)
        fmin = flex.min(fraction)
        assert fmax <= (
            1.0 + 5e-15) and fmax > 0.0, f"{fmax:.16f} not between 0 and 1"
        assert fmin >= 0.0 and fmin <= 1.0

        # Ensure the fraction for each image frame adds up to 1.0 for
        # all those frames completely within the grid
        for j in range(1, fraction.all()[0] - 1):
            tot = flex.sum(fraction[j:j + 1, :])
            assert abs(tot - 1.0) < 1e-7

        # Ensure the frames follow a progression through the grid. I.e,
        # check that values increase then decrease and don't jump around
        for j in range(fraction.all()[0]):
            f = fraction[j:j + 1, :]
            last = f[0]
            rev = False
            for i in range(1, len(f)):
                curr = f[1]
                if rev is False:
                    if curr < last:
                        rev = True
                else:
                    assert curr <= last
                last = curr
Example #20
0
class Test(object):

  def __init__(self):
    from dials.algorithms.profile_model.gaussian_rs import transform
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    import os
    import libtbx.load_env
    from math import floor
    from scitbx import matrix
    from dials.model.serialize import load
    from random import uniform

    try:
      dials_regression = libtbx.env.dist_path('dials_regression')
    except KeyError:
      print 'FAIL: dials_regression not configured'
      exit(0)

    # Set the sweep filename and load the sweep
    filename = os.path.join(
        dials_regression,
        'centroid_test_data',
        'sweep.json')
    self.sweep = load.sweep(filename)

    # Get the models
    self.beam = self.sweep.get_beam()
    self.detector = self.sweep.get_detector()
    self.gonio = self.sweep.get_goniometer()
    assert(len(self.detector) == 1)

    # Get some stuff
    self.s0 = self.beam.get_s0()
    self.m2 = self.gonio.get_rotation_axis()
    self.image_size = self.detector[0].get_image_size()

    # Get a random s1/phi
    i = uniform(0, self.image_size[0])
    j = uniform(1, self.image_size[1])
    self.s1 = matrix.col(self.detector[0].get_pixel_lab_coord((i, j)))
    self.s1 = self.s1.normalize() * matrix.col(self.s0).length()
    self.phi = uniform(0, 5)
    self.x0 = int(floor(i - 10))
    self.y0 = int(floor(j - 10))

    # Set some parameters
    self.sigma_divergence = self.beam.get_sigma_divergence(deg=False)
    self.delta_divergence = 3 * self.sigma_divergence
    self.grid_half_size = 4
    self.step_size = (self.delta_divergence / self.grid_half_size,
                      self.delta_divergence / self.grid_half_size)

    # Create the coordinate system
    self.cs = CoordinateSystem(self.m2, self.s0, self.s1, self.phi)

    # Create the map of s1 coordinates
    self.s1_map = transform.beam_vector_map(self.detector[0], self.beam, True)

    # Create the grid index generator
    self.generate_indices = transform.GridIndexGenerator(
        self.cs,
        self.x0,
        self.y0,
        self.step_size,
        self.grid_half_size,
        self.s1_map)

  def run(self):
    from scitbx import matrix

    for j in range(0, 20):
      for i in range(0, 20):

        xx = self.x0 + i
        yy = self.y0 + j
        if xx < 0 or yy < 0 or xx >= self.image_size[0] or yy >= self.image_size[0]:
          continue

        # Get the grid indices
        gi_1, gj_1 = self.generate_indices(j, i)

        # Get the grid indices
        xyz = matrix.col(self.detector[0].get_pixel_lab_coord(
            (self.x0 + i, self.y0 + j)))
        xyz = xyz.normalize() * matrix.col(self.s0).length()
        c1, c2 = matrix.col(self.cs.from_beam_vector(xyz))
        gi_2 = self.grid_half_size + c1 / self.step_size[0] + 0.5
        gj_2 = self.grid_half_size + c2 / self.step_size[1] + 0.5

        # Check both are the same
        eps = 1e-7
        try:
          assert(abs(gj_1 - gj_2) <= eps)
          assert(abs(gi_1 - gi_2) <= eps)
        except Exception:
          print gi_1, gi_2, gj_1, gj_2
          raise

    # Test passed
    print 'OK'
Example #21
0
def test_map_forward_reverse(dials_data):
    sequence = load.imageset(
        dials_data("centroid_test_data").join("sweep.json").strpath)

    # Get the models
    beam = sequence.get_beam()
    detector = sequence.get_detector()
    gonio = sequence.get_goniometer()
    scan = sequence.get_scan()

    # Set the delta_divergence/mosaicity
    n_sigma = 3
    sigma_divergence = 0.060 * math.pi / 180
    mosaicity = 0.154 * math.pi / 180
    delta_divergence = n_sigma * sigma_divergence
    delta_mosaicity = n_sigma * mosaicity

    # Set the grid size
    grid_size = (4, 4, 4)

    # Create the E3 fraction object
    transform_forward = MapFramesForward(
        scan.get_array_range()[0],
        scan.get_oscillation(deg=False)[0],
        scan.get_oscillation(deg=False)[1],
        mosaicity,
        n_sigma,
        grid_size[2],
    )

    # Create the E3 fraction object
    transform_reverse = MapFramesReverse(
        scan.get_array_range()[0],
        scan.get_oscillation(deg=False)[0],
        scan.get_oscillation(deg=False)[1],
        mosaicity,
        n_sigma,
        grid_size[2],
    )

    # Create the bounding box calculator
    calculate_bbox = BBoxCalculator3D(beam, detector, gonio, scan,
                                      delta_divergence, delta_mosaicity)

    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    for i in range(100):

        # Get random x, y, z
        x = random.uniform(0, 2000)
        y = random.uniform(0, 2000)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, phi, panel)

        # Create the XDS coordinate system
        xcs = CoordinateSystem(m2, s0, s1, phi)

        # Calculate the transform fraction
        forward_fraction = transform_forward(bbox[4:], phi, xcs.zeta())

        # Calculate the transform fraction
        reverse_fraction = transform_reverse(bbox[4:], phi, xcs.zeta())

        # Check the same points are non-zero
        eps = 1e-7
        for j in range(forward_fraction.all()[0]):
            for i in range(forward_fraction.all()[1]):
                if forward_fraction[j, i] > 0.0:
                    assert reverse_fraction[i, j] > 0.0
                else:
                    assert reverse_fraction[i, j] < eps
Example #22
0
    def tst_conservation_of_counts(self):

        from scitbx import matrix
        from random import uniform
        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
        from dials.algorithms.profile_model.gaussian_rs import transform
        from scitbx.array_family import flex

        assert (len(self.detector) == 1)

        s0 = self.beam.get_s0()
        m2 = self.gonio.get_rotation_axis()
        s0_length = matrix.col(self.beam.get_s0()).length()

        # Create an s1 map
        s1_map = transform.beam_vector_map(self.detector[0], self.beam, True)

        for i in range(100):

            # Get random x, y, z
            x = uniform(300, 1800)
            y = uniform(300, 1800)
            z = uniform(0, 9)

            # Get random s1, phi, panel
            s1 = matrix.col(self.detector[0].get_pixel_lab_coord(
                (x, y))).normalize() * s0_length
            phi = self.scan.get_angle_from_array_index(z, deg=False)
            panel = 0

            # Calculate the bounding box
            bbox = self.calculate_bbox(s1, z, panel)
            x0, x1, y0, y1, z0, z1 = bbox

            # Create the coordinate system
            cs = CoordinateSystem(m2, s0, s1, phi)

            # The grid index generator
            step_size = self.delta_divergence / self.grid_size
            grid_index = transform.GridIndexGenerator(cs, x0, y0,
                                                      (step_size, step_size),
                                                      self.grid_size, s1_map)

            # Create the image
            #image = flex.double(flex.grid(z1 - z0, y1 - y0, x1 - x0), 1)
            image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
                             (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))
            mask = flex.bool(flex.grid(image.all()), False)
            for j in range(y1 - y0):
                for i in range(x1 - x0):
                    inside = False
                    gx00, gy00 = grid_index(j, i)
                    gx01, gy01 = grid_index(j, i + 1)
                    gx10, gy10 = grid_index(j + 1, i)
                    gx11, gy11 = grid_index(j + 1, i + 1)
                    mingx = min([gx00, gx01, gx10, gx11])
                    maxgx = max([gx00, gx01, gx10, gx11])
                    mingy = min([gy00, gy01, gy10, gy11])
                    maxgy = max([gy00, gy01, gy10, gy11])
                    if (mingx >= 0 and maxgx < 2 * self.grid_size + 1
                            and mingy >= 0 and maxgy < 2 * self.grid_size + 1):
                        inside = True
                    for k in range(1, z1 - z0 - 1):
                        mask[k, j, i] = inside

            # Transform the image to the grid
            transformed = transform.TransformForward(self.spec, cs, bbox, 0,
                                                     image.as_double(), mask)
            grid = transformed.profile()

            # Get the sums and ensure they're the same
            eps = 1e-7
            sum_grid = flex.sum(grid)
            sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
            assert (abs(sum_grid - sum_image) <= eps)

        # Test passed
        print 'OK'
Example #23
0
def test_forward(dials_data):
    sequence = load.imageset(
        dials_data("centroid_test_data").join("sweep.json").strpath)

    # Get the models
    beam = sequence.get_beam()
    detector = sequence.get_detector()
    gonio = sequence.get_goniometer()
    scan = sequence.get_scan()

    # Set some parameters
    sigma_divergence = beam.get_sigma_divergence(deg=False)
    mosaicity = 0.157 * math.pi / 180
    n_sigma = 3
    grid_size = 7
    delta_divergence = n_sigma * sigma_divergence

    step_size = delta_divergence / grid_size
    delta_divergence2 = delta_divergence + step_size * 0.5
    delta_mosaicity = n_sigma * mosaicity

    # Create the bounding box calculator
    calculate_bbox = BBoxCalculator3D(beam, detector, gonio, scan,
                                      delta_divergence2, delta_mosaicity)

    # Initialise the transform
    spec = transform.TransformSpec(beam, detector, gonio, scan,
                                   sigma_divergence, mosaicity, n_sigma + 1,
                                   grid_size)

    # tst_conservation_of_counts(self):

    assert len(detector) == 1

    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    # Create an s1 map
    s1_map = transform.beam_vector_map(detector[0], beam, True)

    for i in range(100):

        # Get random x, y, z
        x = random.uniform(300, 1800)
        y = random.uniform(300, 1800)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, z, panel)
        x0, x1, y0, y1, z0, z1 = bbox

        # Create the coordinate system
        cs = CoordinateSystem(m2, s0, s1, phi)

        # The grid index generator
        step_size = delta_divergence / grid_size
        grid_index = transform.GridIndexGenerator(cs, x0, y0,
                                                  (step_size, step_size),
                                                  grid_size, s1_map)

        # Create the image
        # image = flex.double(flex.grid(z1 - z0, y1 - y0, x1 - x0), 1)
        image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
                         (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))
        mask = flex.bool(flex.grid(image.all()), False)
        for j in range(y1 - y0):
            for i in range(x1 - x0):
                inside = False
                gx00, gy00 = grid_index(j, i)
                gx01, gy01 = grid_index(j, i + 1)
                gx10, gy10 = grid_index(j + 1, i)
                gx11, gy11 = grid_index(j + 1, i + 1)
                mingx = min([gx00, gx01, gx10, gx11])
                maxgx = max([gx00, gx01, gx10, gx11])
                mingy = min([gy00, gy01, gy10, gy11])
                maxgy = max([gy00, gy01, gy10, gy11])
                if (mingx >= 0 and maxgx < 2 * grid_size + 1 and mingy >= 0
                        and maxgy < 2 * grid_size + 1):
                    inside = True
                for k in range(1, z1 - z0 - 1):
                    mask[k, j, i] = inside

        # Transform the image to the grid
        transformed = transform.TransformForward(spec, cs, bbox, 0,
                                                 image.as_double(), mask)
        grid = transformed.profile()

        # Get the sums and ensure they're the same
        eps = 1e-7
        sum_grid = flex.sum(grid)
        sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
        assert abs(sum_grid - sum_image) <= eps

    # Test passed

    # tst_transform_with_background(self):

    assert len(detector) == 1
    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    # Create an s1 map
    s1_map = transform.beam_vector_map(detector[0], beam, True)

    for i in range(100):

        # Get random x, y, z
        x = random.uniform(300, 1800)
        y = random.uniform(300, 1800)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, z, panel)
        x0, x1, y0, y1, z0, z1 = bbox

        # Create the coordinate system
        cs = CoordinateSystem(m2, s0, s1, phi)

        # The grid index generator
        step_size = delta_divergence / grid_size
        grid_index = transform.GridIndexGenerator(cs, x0, y0,
                                                  (step_size, step_size),
                                                  grid_size, s1_map)

        # Create the image
        # image = flex.double(flex.grid(z1 - z0, y1 - y0, x1 - x0), 1)
        image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
                         (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))
        background = flex.random_double(len(image))
        background.resize(image.accessor())
        mask = flex.bool(flex.grid(image.all()), False)
        for j in range(y1 - y0):
            for i in range(x1 - x0):
                inside = False
                gx00, gy00 = grid_index(j, i)
                gx01, gy01 = grid_index(j, i + 1)
                gx10, gy10 = grid_index(j + 1, i)
                gx11, gy11 = grid_index(j + 1, i + 1)
                mingx = min([gx00, gx01, gx10, gx11])
                maxgx = max([gx00, gx01, gx10, gx11])
                mingy = min([gy00, gy01, gy10, gy11])
                maxgy = max([gy00, gy01, gy10, gy11])
                if (mingx >= 0 and maxgx <= 2 * grid_size + 1 and mingy >= 0
                        and maxgy <= 2 * grid_size + 1):
                    inside = True
                for k in range(1, z1 - z0 - 1):
                    mask[k, j, i] = inside

        # Transform the image to the grid
        transformed = transform.TransformForward(spec, cs, bbox, 0,
                                                 image.as_double(),
                                                 background.as_double(), mask)
        igrid = transformed.profile()
        bgrid = transformed.background()

        # Get the sums and ensure they're the same
        eps = 1e-7
        sum_igrid = flex.sum(igrid)
        sum_bgrid = flex.sum(bgrid)
        sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
        sum_bkgrd = flex.sum(flex.double(flex.select(background, flags=mask)))
        try:
            assert abs(sum_igrid - sum_image) <= eps
            assert abs(sum_bgrid - sum_bkgrd) <= eps
        except Exception:
            print("Failed for: ", (x, y, z))
            raise
Example #24
0
    def tst_conservation_of_counts(self):

        from scitbx import matrix
        from random import uniform, seed
        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
        from dials.algorithms.profile_model.gaussian_rs import transform
        from scitbx.array_family import flex

        seed(0)

        assert len(self.detector) == 1

        s0 = self.beam.get_s0()
        m2 = self.gonio.get_rotation_axis()
        s0_length = matrix.col(self.beam.get_s0()).length()

        # Create an s1 map
        s1_map = transform.beam_vector_map(self.detector[0], self.beam, True)

        for i in range(100):

            # Get random x, y, z
            x = uniform(300, 1800)
            y = uniform(300, 1800)
            z = uniform(500, 600)

            # Get random s1, phi, panel
            s1 = matrix.col(self.detector[0].get_pixel_lab_coord((x, y))).normalize() * s0_length
            phi = self.scan.get_angle_from_array_index(z, deg=False)
            panel = 0

            # Calculate the bounding box
            bbox = self.calculate_bbox(s1, z, panel)
            x0, x1, y0, y1, z0, z1 = bbox

            # Create the coordinate system
            cs = CoordinateSystem(m2, s0, s1, phi)
            if abs(cs.zeta()) < 0.1:
                continue

            # The grid index generator
            step_size = self.delta_divergence / self.grid_size
            grid_index = transform.GridIndexGenerator(cs, x0, y0, (step_size, step_size), self.grid_size, s1_map)

            # Create the image
            # image = flex.double(flex.grid(z1 - z0, y1 - y0, x1 - x0), 1)
            image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0, (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))
            mask = flex.bool(flex.grid(image.all()), False)
            for j in range(y1 - y0):
                for i in range(x1 - x0):
                    inside = False
                    gx00, gy00 = grid_index(j, i)
                    gx01, gy01 = grid_index(j, i + 1)
                    gx10, gy10 = grid_index(j + 1, i)
                    gx11, gy11 = grid_index(j + 1, i + 1)
                    mingx = min([gx00, gx01, gx10, gx11])
                    maxgx = max([gx00, gx01, gx10, gx11])
                    mingy = min([gy00, gy01, gy10, gy11])
                    maxgy = max([gy00, gy01, gy10, gy11])
                    if mingx >= 0 and maxgx < 2 * self.grid_size + 1 and mingy >= 0 and maxgy < 2 * self.grid_size + 1:
                        inside = True
                    for k in range(1, z1 - z0 - 1):
                        mask[k, j, i] = inside

            # Transform the image to the grid
            transformed = transform.TransformForwardNoModel(self.spec, cs, bbox, 0, image.as_double(), mask)
            grid = transformed.profile()

            # Get the sums and ensure they're the same
            eps = 1e-7
            sum_grid = flex.sum(grid)
            sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
            assert abs(sum_grid - sum_image) <= eps

            mask = flex.bool(flex.grid(image.all()), True)
            transformed = transform.TransformForwardNoModel(self.spec, cs, bbox, 0, image.as_double(), mask)
            grid = transformed.profile()

            # Boost the bbox to make sure all intensity is included
            x0, x1, y0, y1, z0, z1 = bbox
            bbox2 = (x0 - 10, x1 + 10, y0 - 10, y1 + 10, z0 - 10, z1 + 10)

            # Do the reverse transform
            transformed = transform.TransformReverseNoModel(self.spec, cs, bbox2, 0, grid)
            image2 = transformed.profile()

            # Check the sum of pixels are the same
            sum_grid = flex.sum(grid)
            sum_image = flex.sum(image2)
            assert abs(sum_grid - sum_image) <= eps

            # Do the reverse transform
            transformed = transform.TransformReverseNoModel(self.spec, cs, bbox, 0, grid)
            image2 = transformed.profile()

            from dials.algorithms.statistics import pearson_correlation_coefficient

            cc = pearson_correlation_coefficient(image.as_1d().as_double(), image2.as_1d())
            assert cc >= 0.99
            # if cc < 0.99:
            #   print cc, bbox
            #   from matplotlib import pylab
            # pylab.plot(image.as_numpy_array()[(z1-z0)/2,(y1-y0)/2,:])
            # pylab.show()
            # pylab.plot(image2.as_numpy_array()[(z1-z0)/2,(y1-y0)/2,:])
            # pylab.show()
            # pylab.plot((image.as_double()-image2).as_numpy_array()[(z1-z0)/2,(y1-y0)/2,:])
            # pylab.show()

        # Test passed
        print "OK"
    def run(self):
        from scitbx import matrix
        from scitbx.array_family import flex
        from dials.algorithms.shoebox import MaskCode
        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
        from math import sqrt
        assert (len(self.detector) == 1)
        s0 = self.beam.get_s0()
        m2 = self.goniometer.get_rotation_axis()
        s0_length = matrix.col(self.beam.get_s0()).length()
        width, height = self.detector[0].get_image_size()
        zrange = self.scan.get_array_range()
        phi0, dphi = self.scan.get_oscillation(deg=False)

        # Generate some reflections
        reflections = self.generate_reflections(10)

        # Mask the foreground in each
        self.mask_foreground(reflections['shoebox'], reflections['s1'],
                             reflections['xyzcal.px'].parts()[2],
                             reflections['panel'])

        # Loop through all the reflections and check the mask values
        shoebox = reflections['shoebox']
        beam_vector = reflections['s1']
        rotation_angle = reflections['xyzcal.mm'].parts()[2]
        for l in range(len(reflections)):
            mask = shoebox[l].mask
            x0, x1, y0, y1, z0, z1 = shoebox[l].bbox
            s1 = beam_vector[l]
            phi = rotation_angle[l]
            cs = CoordinateSystem(m2, s0, s1, phi)

            def rs_coord(i, j, k):
                s1d = self.detector[0].get_pixel_lab_coord((i, j))
                s1d = matrix.col(s1d).normalize() * s0_length
                e1, e2 = cs.from_beam_vector(s1d)
                e3 = cs.from_rotation_angle_fast(phi0 + (k - zrange[0]) * dphi)
                return e1, e2, e3

            new_mask = flex.int(mask.accessor(), 0)
            for k in range(z1 - z0):
                for j in range(y1 - y0):
                    for i in range(x1 - x0):
                        #value1 = mask[k, j, i]
                        e11, e12, e13 = rs_coord(x0 + i, y0 + j, z0 + k)
                        e21, e22, e23 = rs_coord(x0 + i + 1, y0 + j, z0 + k)
                        e31, e32, e33 = rs_coord(x0 + i, y0 + j + 1, z0 + k)
                        e41, e42, e43 = rs_coord(x0 + i, y0 + j, z0 + k + 1)
                        e51, e52, e53 = rs_coord(x0 + i + 1, y0 + j + 1,
                                                 z0 + k)
                        e61, e62, e63 = rs_coord(x0 + i + 1, y0 + j,
                                                 z0 + k + 1)
                        e71, e72, e73 = rs_coord(x0 + i, y0 + j + 1,
                                                 z0 + k + 1)
                        e81, e82, e83 = rs_coord(x0 + i + 1, y0 + j + 1,
                                                 z0 + k + 1)
                        de1 = (e11 / self.delta_d)**2 + (
                            e12 / self.delta_d)**2  #+(e13/self.delta_m)**2
                        de2 = (e21 / self.delta_d)**2 + (
                            e22 / self.delta_d)**2  #+(e23/self.delta_m)**2
                        de3 = (e31 / self.delta_d)**2 + (
                            e32 / self.delta_d)**2  #+(e33/self.delta_m)**2
                        de4 = (e41 / self.delta_d)**2 + (
                            e42 / self.delta_d)**2  #+(e43/self.delta_m)**2
                        de5 = (e51 / self.delta_d)**2 + (
                            e52 / self.delta_d)**2  #+(e53/self.delta_m)**2
                        de6 = (e61 / self.delta_d)**2 + (
                            e62 / self.delta_d)**2  #+(e63/self.delta_m)**2
                        de7 = (e71 / self.delta_d)**2 + (
                            e72 / self.delta_d)**2  #+(e73/self.delta_m)**2
                        de8 = (e81 / self.delta_d)**2 + (
                            e82 / self.delta_d)**2  #+(e83/self.delta_m)**2
                        de = sqrt(min([de1, de2, de3, de4, de5, de6, de7,
                                       de8]))
                        gx = min([e11, e21, e31, e41, e51, e61, e71, e81])
                        gy = min([e12, e22, e32, e42, e52, e62, e72, e82])
                        gz = min([e13, e23, e33, e43, e53, e63, e73, e83])
                        dee = (gx / self.delta_d)**2 + (
                            gy / self.delta_d)**2  # + (gz/self.delta_m)**2
                        #print sqrt(dee), de
                        if (x0 + i < 0 or y0 + j < 0 or x0 + i >= width
                                or y0 + j >= height or z0 + k < zrange[0]
                                or z0 + k >= zrange[1]):
                            value2 = MaskCode.Valid
                        else:
                            if de <= 1.0:
                                value2 = MaskCode.Valid | MaskCode.Foreground
                            else:
                                value2 = MaskCode.Valid | MaskCode.Background
                        new_mask[k, j, i] = value2

            try:
                assert (all(m1 == m2 for m1, m2 in zip(mask, new_mask)))
            except Exception:
                import numpy
                numpy.set_printoptions(threshold=10000)
                diff = (mask == new_mask).as_numpy_array()
                print diff.astype(numpy.int)
                #print mask.as_numpy_array()
                #print new_mask.as_numpy_array()
                #print (new_mask.as_numpy_array()[:,:,:] %2) * (new_mask.as_numpy_array() == 5)
                raise

        # Test passed
        print 'OK'
Example #26
0
def integrate(experiments, reflections, reference):
    from dials.algorithms.profile_model.modeller import CircleSampler
    from dials.array_family import flex
    from dials.algorithms.profile_model.gaussian_rs.transform import TransformReverse
    from dials.algorithms.profile_model.gaussian_rs.transform import TransformForward
    from dials.algorithms.profile_model.gaussian_rs.transform import (
        TransformReverseNoModel, )
    from dials.algorithms.profile_model.gaussian_rs.transform import TransformSpec
    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem

    selection = reflections.get_flags(reflections.flags.integrated_sum)
    reflections = reflections.select(selection)
    print("Selected %d reflections to integrate" % len(reflections))

    sampler = CircleSampler(
        experiments[0].detector[0].get_image_size(),
        experiments[0].scan.get_array_range(),
        1,
    )

    n_sigma = 4.0
    grid_size = 25
    spec = TransformSpec(
        experiments[0].beam,
        experiments[0].detector,
        experiments[0].goniometer,
        experiments[0].scan,
        experiments[0].profile.sigma_b(deg=False),
        experiments[0].profile.sigma_m(deg=False),
        n_sigma,
        grid_size,
    )

    m2 = experiments[0].goniometer.get_rotation_axis()
    s0 = experiments[0].beam.get_s0()

    Iprf = flex.double(len(reflections))
    Vprf = flex.double(len(reflections))
    Cprf = flex.double(len(reflections))
    Fprf = flex.bool(len(reflections))

    for i, r in enumerate(reflections):
        s1 = r["s1"]
        phi = r["xyzcal.mm"][2]
        xyz = r["xyzcal.px"]
        bbox = r["bbox"]
        panel = r["panel"]
        image = r["shoebox"].data.as_double()
        background = r["shoebox"].background.as_double()
        mask = r["shoebox"].mask.as_1d(
        ) == 5  # | (r['shoebox'].mask.as_1d() == 3)
        mask.reshape(image.accessor())
        cs = CoordinateSystem(m2, s0, s1, phi)

        index = sampler.nearest(0, xyz)

        profile = reference[index]

        # print flex.sum(profile)
        # print r['partiality']

        if False:
            from dials.algorithms.integration.maximum_likelihood import (
                ProfileFittingDouble as ProfileFitting, )

            transform = TransformReverseNoModel(spec, cs, bbox, panel, profile)
            p = transform.profile()
            d = image
            m = mask
            b = background
            # print flex.sum(p)

            ysize, xsize = p.all()[1:3]

            p1 = flex.double(flex.grid(1, ysize, xsize))
            d1 = flex.double(flex.grid(1, ysize, xsize))
            b1 = flex.double(flex.grid(1, ysize, xsize))
            m1 = flex.double(flex.grid(1, ysize, xsize))
            for k in range(p.all()[0]):
                p1 += p[k:k + 1, :, :]
                d1 += d[k:k + 1, :, :]
                b1 += b[k:k + 1, :, :]
                m1 = m[k:k + 1, :, :]

            try:

                fit = ProfileFitting(p1, m1, d1, b1, 1e-3, 1000)
                assert fit.niter() < 1000
                Iprf[i] = fit.intensity()
                Vprf[i] = fit.variance()
                Cprf[i] = fit.correlation()
                Fprf[i] = True
                print(i, fit.intensity(), flex.sum(p1))
                # from matplotlib import pylab
                # pylab.imshow(p1.as_numpy_array()[0,:,:], interpolation='none')
                # pylab.show()
            except Exception:
                pass

        else:
            from dials.algorithms.integration.fit import (
                ProfileFittingDouble as ProfileFitting, )

            try:

                transform = TransformForward(spec, cs, bbox, panel, image,
                                             background, mask)

                index = sampler.nearest(0, xyz)

                p = reference[index]
                d = transform.profile()
                b = transform.background()
                m = p > 0

                fit = ProfileFitting(p, m, d, b, 1e-3, 1000)
                assert fit.niter() < 1000
                Iprf[i] = fit.intensity()
                Vprf[i] = fit.variance()
                Cprf[i] = fit.correlation()
                Fprf[i] = True
                print(i, fit.intensity(), flex.sum(p))
                # from matplotlib import pylab
                # pylab.imshow(p1.as_numpy_array()[0,:,:], interpolation='none')
                # pylab.show()
            except Exception:
                pass

    reflections["intensity.prf.value"] = Iprf
    reflections["intensity.prf.variance"] = Vprf
    reflections["intensity.prf.correlation"] = Cprf
    reflections.set_flags(Fprf, reflections.flags.integrated_prf)

    return reflections
Example #27
0
    def tst_conservation_of_counts(self):

        from scitbx import matrix
        from random import uniform, seed
        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
        from dials.algorithms.profile_model.gaussian_rs import transform
        from scitbx.array_family import flex

        seed(0)

        assert (len(self.detector) == 1)

        s0 = self.beam.get_s0()
        m2 = self.gonio.get_rotation_axis()
        s0_length = matrix.col(self.beam.get_s0()).length()

        # Create an s1 map
        s1_map = transform.beam_vector_map(self.detector[0], self.beam, True)

        for i in range(100):

            # Get random x, y, z
            x = uniform(300, 1800)
            y = uniform(300, 1800)
            z = uniform(500, 600)

            # Get random s1, phi, panel
            s1 = matrix.col(self.detector[0].get_pixel_lab_coord(
                (x, y))).normalize() * s0_length
            phi = self.scan.get_angle_from_array_index(z, deg=False)
            panel = 0

            # Calculate the bounding box
            bbox = self.calculate_bbox(s1, z, panel)
            x0, x1, y0, y1, z0, z1 = bbox

            # Create the coordinate system
            cs = CoordinateSystem(m2, s0, s1, phi)
            if abs(cs.zeta()) < 0.1:
                continue

            # The grid index generator
            step_size = self.delta_divergence / self.grid_size
            grid_index = transform.GridIndexGenerator(cs, x0, y0,
                                                      (step_size, step_size),
                                                      self.grid_size, s1_map)

            # Create the image
            #image = flex.double(flex.grid(z1 - z0, y1 - y0, x1 - x0), 1)
            image = gaussian((z1 - z0, y1 - y0, x1 - x0), 10.0,
                             (z - z0, y - y0, x - x0), (2.0, 2.0, 2.0))
            mask = flex.bool(flex.grid(image.all()), False)
            for j in range(y1 - y0):
                for i in range(x1 - x0):
                    inside = False
                    gx00, gy00 = grid_index(j, i)
                    gx01, gy01 = grid_index(j, i + 1)
                    gx10, gy10 = grid_index(j + 1, i)
                    gx11, gy11 = grid_index(j + 1, i + 1)
                    mingx = min([gx00, gx01, gx10, gx11])
                    maxgx = max([gx00, gx01, gx10, gx11])
                    mingy = min([gy00, gy01, gy10, gy11])
                    maxgy = max([gy00, gy01, gy10, gy11])
                    if (mingx >= 0 and maxgx < 2 * self.grid_size + 1
                            and mingy >= 0 and maxgy < 2 * self.grid_size + 1):
                        inside = True
                    for k in range(1, z1 - z0 - 1):
                        mask[k, j, i] = inside

            # Transform the image to the grid
            transformed = transform.TransformForwardNoModel(
                self.spec, cs, bbox, 0, image.as_double(), mask)
            grid = transformed.profile()

            # Get the sums and ensure they're the same
            eps = 1e-7
            sum_grid = flex.sum(grid)
            sum_image = flex.sum(flex.double(flex.select(image, flags=mask)))
            assert (abs(sum_grid - sum_image) <= eps)

            mask = flex.bool(flex.grid(image.all()), True)
            transformed = transform.TransformForwardNoModel(
                self.spec, cs, bbox, 0, image.as_double(), mask)
            grid = transformed.profile()

            # Boost the bbox to make sure all intensity is included
            x0, x1, y0, y1, z0, z1 = bbox
            bbox2 = (x0 - 10, x1 + 10, y0 - 10, y1 + 10, z0 - 10, z1 + 10)

            # Do the reverse transform
            transformed = transform.TransformReverseNoModel(
                self.spec, cs, bbox2, 0, grid)
            image2 = transformed.profile()

            # Check the sum of pixels are the same
            sum_grid = flex.sum(grid)
            sum_image = flex.sum(image2)
            assert (abs(sum_grid - sum_image) <= eps)

            # Do the reverse transform
            transformed = transform.TransformReverseNoModel(
                self.spec, cs, bbox, 0, grid)
            image2 = transformed.profile()

            from dials.algorithms.statistics import pearson_correlation_coefficient
            cc = pearson_correlation_coefficient(image.as_1d().as_double(),
                                                 image2.as_1d())
            assert (cc >= 0.99)
            # if cc < 0.99:
            #   print cc, bbox
            #   from matplotlib import pylab
            # pylab.plot(image.as_numpy_array()[(z1-z0)/2,(y1-y0)/2,:])
            # pylab.show()
            # pylab.plot(image2.as_numpy_array()[(z1-z0)/2,(y1-y0)/2,:])
            # pylab.show()
            # pylab.plot((image.as_double()-image2).as_numpy_array()[(z1-z0)/2,(y1-y0)/2,:])
            # pylab.show()

        # Test passed
        print 'OK'
Example #28
0
def test_map_frames_reverse(dials_data):
    from dials.model.serialize import load
    from dials.algorithms.profile_model.gaussian_rs.transform import MapFramesReverse
    from dials.algorithms.profile_model.gaussian_rs import BBoxCalculator3D

    sequence = load.sequence(
        dials_data("centroid_test_data").join("sweep.json").strpath)

    # Get the models
    beam = sequence.get_beam()
    detector = sequence.get_detector()
    gonio = sequence.get_goniometer()
    scan = sequence.get_scan()

    # Set the delta_divergence/mosaicity
    n_sigma = 3
    sigma_divergence = 0.060 * math.pi / 180
    mosaicity = 0.154 * math.pi / 180
    delta_divergence = n_sigma * sigma_divergence
    delta_mosaicity = n_sigma * mosaicity

    # Set the grid size
    grid_size = (4, 4, 4)

    # Create the E3 fraction object
    transform = MapFramesReverse(
        scan.get_array_range()[0],
        scan.get_oscillation(deg=False)[0],
        scan.get_oscillation(deg=False)[1],
        mosaicity,
        n_sigma,
        grid_size[2],
    )

    # Create the bounding box calculator
    calculate_bbox = BBoxCalculator3D(beam, detector, gonio, scan,
                                      delta_divergence, delta_mosaicity)

    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    from scitbx.array_family import flex

    s0 = beam.get_s0()
    m2 = gonio.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()

    for i in range(100):

        # Get random x, y, z
        x = random.uniform(0, 2000)
        y = random.uniform(0, 2000)
        z = random.uniform(0, 9)

        # Get random s1, phi, panel
        s1 = matrix.col(detector[0].get_pixel_lab_coord(
            (x, y))).normalize() * s0_length
        phi = scan.get_angle_from_array_index(z, deg=False)
        panel = 0

        # Calculate the bounding box
        bbox = calculate_bbox(s1, phi, panel)
        x1, x2 = bbox[0], bbox[1]
        y1, y2 = bbox[2], bbox[3]
        z1, z2 = bbox[4], bbox[5]
        if x1 == 0 or y1 == 0 or z1 == 0:
            continue
        if x2 == 2000 or y2 == 2000 or z2 == 9:
            continue

        # Create the XDS coordinate system
        xcs = CoordinateSystem(m2, s0, s1, phi)

        # Calculate the transform fraction
        fraction = transform(bbox[4:], phi, xcs.zeta())

        # Ensure the minimum and maximum are 0 < 1
        fmax = flex.max(fraction)
        fmin = flex.min(fraction)
        assert fmax <= 1.0 and fmax > 0.0
        assert fmin >= 0.0 and fmin <= 1.0

        # Ensure the fraction for image adds up to 1.0 for
        # all those images completely within the image
        for v3 in range(fraction.all()[0]):
            tot = flex.sum(fraction[v3:v3 + 1, :])
            assert abs(tot - 1.0) < 1e-7

        # Ensure the frames follow a progression through the grid. I.e,
        # check that values increase then decrease and don't jump around
        for v3 in range(fraction.all()[0]):
            f = fraction[v3:v3 + 1, :]
            last = f[0]
            rev = False
            for i in range(1, len(f)):
                curr = f[1]
                if rev is False:
                    if curr < last:
                        rev = True
                else:
                    assert curr <= last
                last = curr
def test(dials_data):
    from dxtbx.model.experiment_list import Experiment, ExperimentList
    from dxtbx.serialize import load

    from dials.algorithms.profile_model.gaussian_rs import MaskCalculator3D, Model

    sequence = load.imageset(
        dials_data("centroid_test_data").join("sweep.json").strpath)
    crystal = load.crystal(
        dials_data("centroid_test_data").join("crystal.json").strpath)

    beam = sequence.get_beam()
    detector = sequence.get_detector()
    goniometer = sequence.get_goniometer()
    scan = sequence.get_scan()
    delta_d = 3 * beam.get_sigma_divergence(deg=False)
    try:
        mosaicity = crystal.get_mosaicity(deg=False)
    except AttributeError:
        mosaicity = 0
    delta_m = 3 * mosaicity
    nsigma = 3
    profile_model = Model(None, nsigma, beam.get_sigma_divergence(deg=False),
                          mosaicity)
    experiment = ExperimentList()
    experiment.append(
        Experiment(
            imageset=sequence,
            beam=beam,
            detector=detector,
            goniometer=goniometer,
            scan=scan,
            crystal=crystal,
            profile=profile_model,
        ))

    assert len(detector) == 1

    # Get the function object to mask the foreground
    mask_foreground = MaskCalculator3D(beam, detector, goniometer, scan,
                                       delta_d, delta_m)

    from scitbx.array_family import flex

    from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem
    from dials.algorithms.shoebox import MaskCode

    s0 = beam.get_s0()
    m2 = goniometer.get_rotation_axis()
    s0_length = matrix.col(beam.get_s0()).length()
    width, height = detector[0].get_image_size()
    zrange = scan.get_array_range()
    phi0, dphi = scan.get_oscillation(deg=False)

    # Generate some reflections
    reflections = generate_reflections(detector, beam, scan, experiment, 10)

    # Mask the foreground in each
    mask_foreground(
        reflections["shoebox"],
        reflections["s1"],
        reflections["xyzcal.px"].parts()[2],
        reflections["panel"],
    )

    # Loop through all the reflections and check the mask values
    shoebox = reflections["shoebox"]
    beam_vector = reflections["s1"]
    rotation_angle = reflections["xyzcal.mm"].parts()[2]
    for l in range(len(reflections)):
        mask = shoebox[l].mask
        x0, x1, y0, y1, z0, z1 = shoebox[l].bbox
        s1 = beam_vector[l]
        phi = rotation_angle[l]
        cs = CoordinateSystem(m2, s0, s1, phi)

        def rs_coord(i, j, k):
            s1d = detector[0].get_pixel_lab_coord((i, j))
            s1d = matrix.col(s1d).normalize() * s0_length
            e1, e2 = cs.from_beam_vector(s1d)
            e3 = cs.from_rotation_angle_fast(phi0 + (k - zrange[0]) * dphi)
            return e1, e2, e3

        new_mask = flex.int(mask.accessor(), 0)
        for k in range(z1 - z0):
            for j in range(y1 - y0):
                for i in range(x1 - x0):
                    # value1 = mask[k, j, i]
                    e11, e12, e13 = rs_coord(x0 + i, y0 + j, z0 + k)
                    e21, e22, e23 = rs_coord(x0 + i + 1, y0 + j, z0 + k)
                    e31, e32, e33 = rs_coord(x0 + i, y0 + j + 1, z0 + k)
                    e41, e42, e43 = rs_coord(x0 + i, y0 + j, z0 + k + 1)
                    e51, e52, e53 = rs_coord(x0 + i + 1, y0 + j + 1, z0 + k)
                    e61, e62, e63 = rs_coord(x0 + i + 1, y0 + j, z0 + k + 1)
                    e71, e72, e73 = rs_coord(x0 + i, y0 + j + 1, z0 + k + 1)
                    e81, e82, e83 = rs_coord(x0 + i + 1, y0 + j + 1,
                                             z0 + k + 1)
                    de1 = (e11 / delta_d)**2 + (
                        e12 / delta_d)**2  # +(e13/delta_m)**2
                    de2 = (e21 / delta_d)**2 + (
                        e22 / delta_d)**2  # +(e23/delta_m)**2
                    de3 = (e31 / delta_d)**2 + (
                        e32 / delta_d)**2  # +(e33/delta_m)**2
                    de4 = (e41 / delta_d)**2 + (
                        e42 / delta_d)**2  # +(e43/delta_m)**2
                    de5 = (e51 / delta_d)**2 + (
                        e52 / delta_d)**2  # +(e53/delta_m)**2
                    de6 = (e61 / delta_d)**2 + (
                        e62 / delta_d)**2  # +(e63/delta_m)**2
                    de7 = (e71 / delta_d)**2 + (
                        e72 / delta_d)**2  # +(e73/delta_m)**2
                    de8 = (e81 / delta_d)**2 + (
                        e82 / delta_d)**2  # +(e83/delta_m)**2
                    de = math.sqrt(
                        min([de1, de2, de3, de4, de5, de6, de7, de8]))
                    if (x0 + i < 0 or y0 + j < 0 or x0 + i >= width
                            or y0 + j >= height or z0 + k < zrange[0]
                            or z0 + k >= zrange[1]):
                        value2 = MaskCode.Valid
                    else:
                        if de <= 1.0:
                            value2 = MaskCode.Valid | MaskCode.Foreground
                        else:
                            value2 = MaskCode.Valid | MaskCode.Background
                    new_mask[k, j, i] = value2

        if not all(m1 == m2 for m1, m2 in zip(mask, new_mask)):
            np.set_printoptions(threshold=10000)
            diff = (mask == new_mask).as_numpy_array()
            print(diff.astype(np.int))
            # print mask.as_numpy_array()
            # print new_mask.as_numpy_array()
            # print (new_mask.as_numpy_array()[:,:,:] %2) * (new_mask.as_numpy_array() == 5)
            assert False
    def tst_outer_bounds(self):

        from scitbx import matrix
        from random import uniform
        from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem

        assert (len(self.detector) == 1)
        s0 = self.beam.get_s0()
        m2 = self.gonio.get_rotation_axis()
        s0_length = matrix.col(self.beam.get_s0()).length()
        width, height = self.detector[0].get_image_size()
        zrange = self.scan.get_array_range()

        for i in range(1000):

            # Get random x, y, z
            x = uniform(0, 2000)
            y = uniform(0, 2000)
            z = uniform(0, 9)

            # Get random s1, phi, panel
            s1 = matrix.col(self.detector[0].get_pixel_lab_coord(
                (x, y))).normalize() * s0_length
            phi = self.scan.get_angle_from_array_index(z, deg=False)
            panel = 0

            # Calculate the bounding box
            bbox = self.calculate_bbox(s1, z, panel)
            x1, x2 = bbox[0], bbox[1]
            y1, y2 = bbox[2], bbox[3]
            z1, z2 = bbox[4], bbox[5]

            # Calculate the rotation angle for each point
            phi_dash1 = self.scan.get_angle_from_array_index(z1, deg=False)
            phi_dash2 = self.scan.get_angle_from_array_index(z2, deg=False)

            # Create the XDS coordinate system
            xcs = CoordinateSystem(m2, s0, s1, phi)

            # Calculate reciprocal space coordinates at each point
            e11, e21, e31 = xcs.from_beam_vector_and_rotation_angle(
                s1, phi_dash1)
            e12, e22, e32 = xcs.from_beam_vector_and_rotation_angle(
                s1, phi_dash2)

            # Check vertical edges
            for j in range(bbox[2], bbox[3] + 1):
                xyz1 = self.detector[0].get_pixel_lab_coord((bbox[0], j))
                xyz2 = self.detector[0].get_pixel_lab_coord((bbox[1] + 1, j))
                sdash1 = matrix.col(xyz1).normalize() * s0_length
                sdash2 = matrix.col(xyz2).normalize() * s0_length
                e11, e21, e3 = xcs.from_beam_vector_and_rotation_angle(
                    sdash1, phi)
                e12, e22, e3 = xcs.from_beam_vector_and_rotation_angle(
                    sdash2, phi)
                if bbox[0] > 0 and bbox[1] < width:
                    assert (abs(e11) >= self.delta_divergence
                            or abs(e21) >= self.delta_divergence)
                    assert (abs(e12) >= self.delta_divergence
                            or abs(e22) >= self.delta_divergence)

            # Check horizontal edges
            for i in range(bbox[0], bbox[1] + 1):
                xyz1 = self.detector[0].get_pixel_lab_coord((i, bbox[2]))
                xyz2 = self.detector[0].get_pixel_lab_coord((i, bbox[3] + 1))
                sdash1 = matrix.col(xyz1).normalize() * s0_length
                sdash2 = matrix.col(xyz2).normalize() * s0_length
                e11, e21, e3 = xcs.from_beam_vector_and_rotation_angle(
                    sdash1, phi)
                e12, e22, e3 = xcs.from_beam_vector_and_rotation_angle(
                    sdash2, phi)
                if bbox[2] > 0 and bbox[3] < height:
                    assert (abs(e11) >= self.delta_divergence
                            or abs(e21) >= self.delta_divergence)
                    assert (abs(e12) >= self.delta_divergence
                            or abs(e22) >= self.delta_divergence)

            # All e3 coords >= delta_mosaicity
            if bbox[4] > zrange[0] and bbox[5] < zrange[1]:
                assert (abs(e31) >= self.delta_mosaicity)
                assert (abs(e32) >= self.delta_mosaicity)

        print 'OK'