コード例 #1
0
  def test_num_intervals(self, nintervals):
    """Test a range of different numbers of intervals"""

    # Parameterise the detector with the image range and five intervals. Init
    # TestOrientationModel to explore gradients at image 50
    det_p = TestDetectorModel(50, self.detector, self.image_range, nintervals)

    # How many parameters?
    num_param = det_p.num_free()

    # apply a random parameter shift to the detector, on order of 2% of
    # the initial values
    p_vals = det_p.get_param_vals()
    sigmas = [0.02  * p for p in p_vals]
    new_vals = random_param_shift(p_vals, sigmas)
    det_p.set_param_vals(new_vals)

    # calculate state and gradients at image 50
    det_p.compose()

    null_mat = matrix.sqr((0., 0., 0., 0., 0., 0., 0., 0., 0.))

    # compare analytical and finite difference derivatives at image 50
    an_ds_dp = det_p.get_ds_dp()
    fd_ds_dp = get_fd_gradients(det_p, [1.e-7] * num_param)
    param_names = det_p.get_param_names()

    for e, f in zip(an_ds_dp, fd_ds_dp):
      assert(approx_equal((e - f), null_mat, eps = 1.e-6))

    print "OK"
    return
コード例 #2
0
def test_ScanVaryingDetectorParameterisation(nintervals, plots=False):
    """Basic test of a ScanVaryingDetectorParameterisationSinglePanel
    with a range of different numbers of intervals"""

    vmp = _TestScanVaryingModelParameterisation()

    # Parameterise the detector with the image range and five intervals. Init
    # TestOrientationModel to explore gradients at image 50
    det_p = _TestDetectorModel(50, vmp.detector, vmp.image_range, nintervals)

    # How many parameters?
    num_param = det_p.num_free()

    # apply a random parameter shift to the detector, on order of 2% of
    # the initial values
    p_vals = det_p.get_param_vals()
    sigmas = [0.02 * p for p in p_vals]
    new_vals = random_param_shift(p_vals, sigmas)
    det_p.set_param_vals(new_vals)

    # calculate state and gradients at image 50
    det_p.compose()

    null_mat = matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0))

    # compare analytical and finite difference derivatives at image 50
    an_ds_dp = det_p.get_ds_dp()
    fd_ds_dp = get_fd_gradients(det_p, [1.0e-7] * num_param)

    for e, f in zip(an_ds_dp, fd_ds_dp):
        assert approx_equal((e - f), null_mat, eps=1.0e-6)
コード例 #3
0
def test_ScanVaryingCrystalOrientationParameterisation_random(plots=False):
    """Test a ScanVaryingCrystalOrientationParameterisation with
    random initial orientations, random parameter shifts and random times"""

    vmp = _TestScanVaryingModelParameterisation()

    attempts = 100
    null_mat = matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0))

    for i in range(attempts):
        # make a new P1 random crystal and parameterise it
        a = random.uniform(10, 50) * vmp.random_direction_close_to(
            matrix.col((1, 0, 0)))
        b = random.uniform(10, 50) * vmp.random_direction_close_to(
            matrix.col((0, 1, 0)))
        c = random.uniform(10, 50) * vmp.random_direction_close_to(
            matrix.col((0, 0, 1)))
        xl = Crystal(a, b, c, space_group_symbol="P 1")

        xl_op = _TestOrientationModel(50, xl, vmp.image_range, 5)

        # How many parameters?
        num_param = xl_op.num_free()

        # apply random parameter shifts to the orientation (2.0 mrad each
        # checkpoint)
        p_vals = xl_op.get_param_vals()
        sigmas = [2.0] * len(p_vals)
        new_vals = random_param_shift(p_vals, sigmas)
        xl_op.set_param_vals(new_vals)

        # select random time point at which to make comparisons
        t = random.uniform(*vmp.image_range)
        xl_op.set_time_point(t)

        # compare analytical and finite difference derivatives
        xl_op_an_ds_dp = xl_op.get_ds_dp()
        xl_op_fd_ds_dp = get_fd_gradients(xl_op,
                                          [1.0e-6 * math.pi / 180] * num_param)

        for j in range(num_param):
            assert approx_equal((xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j]),
                                null_mat,
                                eps=1.0e-6), textwrap.dedent("""\
        Failure in try {i}
        failure for parameter number {j}
        of the orientation parameterisation
        with fd_ds_dp =
        {fd}
        and an_ds_dp =
        {an}
        so that difference fd_ds_dp - an_ds_dp =
        {diff}
        """).format(
                                    i=i,
                                    j=j,
                                    fd=xl_op_fd_ds_dp[j],
                                    an=xl_op_an_ds_dp[j],
                                    diff=xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j],
                                )
コード例 #4
0
def test_ScanVaryingBeamParameterisation(nintervals, plots=False):
    """Basic test of a ScanVaryingBeamParameterisation
     with a range of different numbers of intervals"""

    vmp = _TestScanVaryingModelParameterisation()

    # Parameterise the crystal with the image range and five intervals. Init
    # TestOrientationModel to explore gradients at image 50
    beam_p = _TestBeamModel(50, vmp.beam, vmp.image_range, nintervals,
                            vmp.goniometer)

    # How many parameters?
    num_param = beam_p.num_free()

    # apply a random parameter shift to the beam, on order of 2% of
    # the initial values
    p_vals = beam_p.get_param_vals()
    sigmas = [0.02 * p for p in p_vals]
    new_vals = random_param_shift(p_vals, sigmas)
    beam_p.set_param_vals(new_vals)

    # calculate state and gradients at image 50
    beam_p.compose()

    null_vec = matrix.col((0., 0., 0.))

    # compare analytical and finite difference derivatives at image 50
    an_ds_dp = beam_p.get_ds_dp()
    fd_ds_dp = get_fd_gradients(beam_p, [1.e-7] * num_param)
    param_names = beam_p.get_param_names()

    for e, f in zip(an_ds_dp, fd_ds_dp):
        assert approx_equal((e - f), null_vec, eps=1.e-6)
コード例 #5
0
def test_ScanVaryingCrystalUnitCellParameterisation_intervals(
        nintervals, plots=False):
    """Basic test of a ScanVaryingCrystalUnitCellParameterisation
     with a range of different numbers of intervals"""

    vmp = _TestScanVaryingModelParameterisation()

    # Parameterise the crystal with the image range and five intervals. Init
    # TestOrientationModel to explore gradients at image 50
    xl_ucp = _TestUnitCellModel(50, vmp.xl, vmp.image_range, nintervals)

    # How many parameters?
    num_param = xl_ucp.num_free()

    # apply a random parameter shift to the unit cell, on order of 2% of
    # the initial metrical matrix parameters
    p_vals = xl_ucp.get_param_vals()
    sigmas = [0.02 * p for p in p_vals]
    new_vals = random_param_shift(p_vals, sigmas)
    xl_ucp.set_param_vals(new_vals)

    # calculate state and gradients at image 50
    xl_ucp.compose()

    null_mat = matrix.sqr((0., 0., 0., 0., 0., 0., 0., 0., 0.))

    # compare analytical and finite difference derivatives at image 50
    an_ds_dp = xl_ucp.get_ds_dp()
    fd_ds_dp = get_fd_gradients(xl_ucp, [1.e-7] * num_param)
    param_names = xl_ucp.get_param_names()

    for e, f in zip(an_ds_dp, fd_ds_dp):
        assert approx_equal((e - f), null_mat, eps=1.e-6)
コード例 #6
0
  def test_num_intervals(self, nintervals):
    """Test a range of different numbers of intervals"""

    # Parameterise the detector with the image range and five intervals. Init
    # TestOrientationModel to explore gradients at image 50
    det_p = TestDetectorModel(50, self.detector, self.image_range, nintervals)

    # How many parameters?
    num_param = det_p.num_free()

    # apply a random parameter shift to the detector, on order of 2% of
    # the initial values
    p_vals = det_p.get_param_vals()
    sigmas = [0.02  * p for p in p_vals]
    new_vals = random_param_shift(p_vals, sigmas)
    det_p.set_param_vals(new_vals)

    # calculate state and gradients at image 50
    det_p.compose()

    null_mat = matrix.sqr((0., 0., 0., 0., 0., 0., 0., 0., 0.))

    # compare analytical and finite difference derivatives at image 50
    an_ds_dp = det_p.get_ds_dp()
    fd_ds_dp = get_fd_gradients(det_p, [1.e-7] * num_param)
    param_names = det_p.get_param_names()

    for e, f in zip(an_ds_dp, fd_ds_dp):
      assert(approx_equal((e - f), null_mat, eps = 1.e-6))

    print "OK"
    return
コード例 #7
0
ファイル: test_beam_parameters.py プロジェクト: hattne/dials
def test_beam_parameters():
    from scitbx import matrix

    from dxtbx.model import BeamFactory
    from dials.algorithms.refinement.parameterisation.beam_parameters import (
        BeamParameterisation,
    )
    from dials.algorithms.refinement.refinement_helpers import (
        get_fd_gradients,
        random_param_shift,
    )

    # make a random beam vector and parameterise it
    bf = BeamFactory()
    s0 = bf.make_beam(matrix.col.random(3, 0.5, 1.5), wavelength=1.2)
    s0p = BeamParameterisation(s0)

    # Let's do some basic tests. First, can we change parameter values and
    # update the modelled vector s0?
    s0_old = matrix.col(s0.get_s0())
    s0p.set_param_vals([1000 * 0.1, 1000 * 0.1, 0.8])
    assert matrix.col(s0.get_s0()).angle(s0_old) == pytest.approx(0.1413033, abs=1e-6)
    assert matrix.col(s0.get_s0()).length() == pytest.approx(0.8, abs=1e-6)

    # random initial orientations and wavelengths with a random parameter shifts
    attempts = 1000
    failures = 0
    for i in range(attempts):

        # make a random beam vector and parameterise it
        s0 = bf.make_beam(
            matrix.col.random(3, 0.5, 1.5), wavelength=random.uniform(0.8, 1.5)
        )
        s0p = BeamParameterisation(s0)

        # apply a random parameter shift
        p_vals = s0p.get_param_vals()
        p_vals = random_param_shift(p_vals, [1000 * pi / 9, 1000 * pi / 9, 0.01])
        s0p.set_param_vals(p_vals)

        # compare analytical and finite difference derivatives
        an_ds_dp = s0p.get_ds_dp()
        fd_ds_dp = get_fd_gradients(s0p, [1.0e-5 * pi / 180, 1.0e-5 * pi / 180, 1.0e-6])

        for j in range(3):
            try:
                assert list(fd_ds_dp[j] - an_ds_dp[j]) == pytest.approx(
                    (0, 0, 0), abs=1e-6
                )
            except Exception:
                print("for try", i)
                print("failure for parameter number", j)
                print("with fd_ds_dp = ")
                print(fd_ds_dp[j])
                print("and an_ds_dp = ")
                print(an_ds_dp[j])
                print("so that difference fd_ds_dp - an_ds_dp =")
                print(fd_ds_dp[j] - an_ds_dp[j])
                raise
コード例 #8
0
    def test_random(self):
        """Test random initial orientations, random parameter shifts and random
    times"""

        attempts = 100
        failures = 0
        null_mat = matrix.sqr((0., 0., 0., 0., 0., 0., 0., 0., 0.))

        for i in range(attempts):

            # make a new P1 random crystal and parameterise it
            a = random.uniform(10,50) * \
                    self.random_direction_close_to(matrix.col((1, 0, 0)))
            b = random.uniform(10,50) * \
                    self.random_direction_close_to(matrix.col((0, 1, 0)))
            c = random.uniform(10,50) * \
                    self.random_direction_close_to(matrix.col((0, 0, 1)))
            xl = Crystal(a, b, c, space_group_symbol="P 1")

            xl_op = TestOrientationModel(50, xl, self.image_range, 5)

            # How many parameters?
            num_param = xl_op.num_free()

            # apply random parameter shifts to the orientation (2.0 mrad each
            # checkpoint)
            p_vals = xl_op.get_param_vals()
            sigmas = [2.0] * len(p_vals)
            new_vals = random_param_shift(p_vals, sigmas)
            xl_op.set_param_vals(new_vals)

            # select random time point at which to make comparisons
            t = random.uniform(*self.image_range)
            xl_op.set_time_point(t)

            # compare analytical and finite difference derivatives
            xl_op_an_ds_dp = xl_op.get_ds_dp()
            xl_op_fd_ds_dp = get_fd_gradients(xl_op, [1.e-6 * pi/180] * \
                                              num_param)

            for j in range(num_param):
                try:
                    assert (approx_equal(
                        (xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j]),
                        null_mat,
                        eps=1.e-6))
                except Exception:
                    failures += 1
                    print "for try", i
                    print "failure for parameter number", j
                    print "of the orientation parameterisation"
                    print "with fd_ds_dp = "
                    print xl_op_fd_ds_dp[j]
                    print "and an_ds_dp = "
                    print xl_op_an_ds_dp[j]
                    print "so that difference fd_ds_dp - an_ds_dp ="
                    print xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j]

        if failures == 0: print "OK"
コード例 #9
0
  def test_random(self):
    """Test random initial orientations, random parameter shifts and random
    times"""

    attempts = 100
    failures = 0
    null_mat = matrix.sqr((0., 0., 0., 0., 0., 0., 0., 0., 0.))

    for i in range(attempts):

      # make a new P1 random crystal and parameterise it
      a = random.uniform(10,50) * \
              self.random_direction_close_to(matrix.col((1, 0, 0)))
      b = random.uniform(10,50) * \
              self.random_direction_close_to(matrix.col((0, 1, 0)))
      c = random.uniform(10,50) * \
              self.random_direction_close_to(matrix.col((0, 0, 1)))
      xl = crystal_model(a, b, c, space_group_symbol="P 1")

      xl_op = TestOrientationModel(50, xl, self.image_range, 5)

      # How many parameters?
      num_param = xl_op.num_free()

      # apply random parameter shifts to the orientation (2.0 mrad each
      # checkpoint)
      p_vals = xl_op.get_param_vals()
      sigmas = [2.0] * len(p_vals)
      new_vals = random_param_shift(p_vals, sigmas)
      xl_op.set_param_vals(new_vals)

      # select random time point at which to make comparisons
      t = random.uniform(*self.image_range)
      xl_op.set_time_point(t)

      # compare analytical and finite difference derivatives
      xl_op_an_ds_dp = xl_op.get_ds_dp()
      xl_op_fd_ds_dp = get_fd_gradients(xl_op, [1.e-6 * pi/180] * \
                                        num_param)

      for j in range(num_param):
        try:
          assert(approx_equal((xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j]),
                              null_mat, eps = 1.e-6))
        except Exception:
          failures += 1
          print "for try", i
          print "failure for parameter number", j
          print "of the orientation parameterisation"
          print "with fd_ds_dp = "
          print xl_op_fd_ds_dp[j]
          print "and an_ds_dp = "
          print xl_op_an_ds_dp[j]
          print "so that difference fd_ds_dp - an_ds_dp ="
          print xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j]

    if failures == 0: print "OK"
コード例 #10
0
def test():
    goniometer = random_gonio()
    gonp = GoniometerParameterisation(goniometer)

    # Let's do some basic tests. First, can we change parameter values and
    # update the laboratory frame rotation axis?
    e_lab = matrix.col(goniometer.get_rotation_axis())
    gonp.set_param_vals([1000 * 0.1, 1000 * 0.1])
    assert matrix.col(goniometer.get_rotation_axis()).angle(
        e_lab) == pytest.approx(0.1413033)

    # random goniometers and random parameter shifts
    attempts = 1000
    for i in range(attempts):
        # make a random goniometer and parameterise it
        goniometer = random_gonio()
        gonp = GoniometerParameterisation(goniometer)

        # apply a random parameter shift
        p_vals = gonp.get_param_vals()
        p_vals = random_param_shift(p_vals,
                                    [1000 * math.pi / 9, 1000 * math.pi / 9])
        gonp.set_param_vals(p_vals)

        # compare analytical and finite difference derivatives
        an_ds_dp = gonp.get_ds_dp()
        fd_ds_dp = get_fd_gradients(
            gonp, [1.0e-5 * math.pi / 180, 1.0e-5 * math.pi / 180])

        null_mat = matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0))
        for j in range(2):
            try:
                assert approx_equal((fd_ds_dp[j] - an_ds_dp[j]),
                                    null_mat,
                                    eps=1.0e-6)
            except Exception:
                print("for try", i)
                print("failure for parameter number", j)
                print("with fd_ds_dp = ")
                print(fd_ds_dp[j])
                print("and an_ds_dp = ")
                print(an_ds_dp[j])
                print("so that difference fd_ds_dp - an_ds_dp =")
                print(fd_ds_dp[j] - an_ds_dp[j])
                raise
コード例 #11
0
    for i in range(attempts):

        # make a random P1 crystal and parameterise it
        a = random.uniform(10, 50) * random_direction_close_to(
            matrix.col((1, 0, 0)))
        b = random.uniform(10, 50) * random_direction_close_to(
            matrix.col((0, 1, 0)))
        c = random.uniform(10, 50) * random_direction_close_to(
            matrix.col((0, 0, 1)))
        xl = crystal_model(a, b, c, space_group_symbol="P 1")
        xl_op = CrystalOrientationParameterisation(xl)
        xl_uc = CrystalUnitCellParameterisation(xl)

        # apply a random parameter shift to the orientation
        p_vals = xl_op.get_param_vals()
        p_vals = random_param_shift(
            p_vals, [1000 * pi / 9, 1000 * pi / 9, 1000 * pi / 9])
        xl_op.set_param_vals(p_vals)

        # compare analytical and finite difference derivatives
        xl_op_an_ds_dp = xl_op.get_ds_dp()
        xl_op_fd_ds_dp = get_fd_gradients(xl_op, [1.e-5 * pi / 180] * 3)

        # apply a random parameter shift to the unit cell. We have to
        # do this in a way that is respectful to metrical constraints,
        # so don't modify the parameters directly; modify the cell
        # constants and extract the new parameters
        cell_params = xl.get_unit_cell().parameters()
        cell_params = random_param_shift(cell_params, [1.] * 6)
        new_uc = unit_cell(cell_params)
        newB = matrix.sqr(new_uc.fractionalization_matrix()).transpose()
        S = symmetrize_reduce_enlarge(xl.get_space_group())
コード例 #12
0
  # random initial orientations with a random parameter shift at each
  attempts = 100
  failures = 0
  for i in range(attempts):

    # make a random P1 crystal and parameterise it
    a = random.uniform(10,50) * random_direction_close_to(matrix.col((1, 0, 0)))
    b = random.uniform(10,50) * random_direction_close_to(matrix.col((0, 1, 0)))
    c = random.uniform(10,50) * random_direction_close_to(matrix.col((0, 0, 1)))
    xl = crystal_model(a, b, c, space_group_symbol="P 1")
    xl_op = CrystalOrientationParameterisation(xl)
    xl_uc = CrystalUnitCellParameterisation(xl)

    # apply a random parameter shift to the orientation
    p_vals = xl_op.get_param_vals()
    p_vals = random_param_shift(p_vals, [1000*pi/9, 1000*pi/9,
                                         1000*pi/9])
    xl_op.set_param_vals(p_vals)

    # compare analytical and finite difference derivatives
    xl_op_an_ds_dp = xl_op.get_ds_dp()
    xl_op_fd_ds_dp = get_fd_gradients(xl_op, [1.e-5 * pi/180] * 3)

    # apply a random parameter shift to the unit cell. We have to
    # do this in a way that is respectful to metrical constraints,
    # so don't modify the parameters directly; modify the cell
    # constants and extract the new parameters
    cell_params = xl.get_unit_cell().parameters()
    cell_params = random_param_shift(cell_params, [1.] * 6)
    new_uc = unit_cell(cell_params)
    newB = matrix.sqr(new_uc.fractionalization_matrix()).transpose()
    S = symmetrize_reduce_enlarge(xl.get_space_group())
コード例 #13
0
  def test_num_intervals(self, nintervals):
    """Test a range of different numbers of intervals"""

    # Parameterise the crystal with the image range and five intervals. Init
    # TestOrientationModel to explore gradients at image 50, but actually
    # will try various time points in the test
    xl_op = TestOrientationModel(50, self.xl, self.image_range, nintervals)

    # How many parameters?
    num_param = xl_op.num_free()

    # shift the parameters away from zero
    p_vals = xl_op.get_param_vals()
    sigmas = [1.0] * len(p_vals)
    new_vals = random_param_shift(p_vals, sigmas)
    xl_op.set_param_vals(new_vals)

    # recalc state and gradients at image 50
    xl_op.compose()
    p_vals = xl_op.get_param_vals()
    #print "Shifted parameter vals", p_vals

    # compare analytical and finite difference derivatives at image 50
    an_ds_dp = xl_op.get_ds_dp()
    fd_ds_dp = get_fd_gradients(xl_op, [1.e-6 * pi/180] * num_param)
    param_names = xl_op.get_param_names()

    null_mat = matrix.sqr((0., 0., 0., 0., 0., 0., 0., 0., 0.))
    for e, f in zip(an_ds_dp, fd_ds_dp):
      assert(approx_equal((e - f), null_mat, eps = 1.e-6))

    # Now test gradients at equally spaced time points across the whole
    # range
    num_points = 50
    smooth_at = []
    phi1_data = []
    phi2_data = []
    phi3_data = []
    step_size = (self.image_range[1] - self.image_range[0]) / num_points
    for t in [self.image_range[0] + e * step_size \
                for e in range(num_points + 1)]:

      # collect data for plot
      smooth_at.append(t)
      phi1_data.append(xl_op._smoother.value_weight(t, xl_op._param[0])[0])
      phi2_data.append(xl_op._smoother.value_weight(t, xl_op._param[1])[0])
      phi3_data.append(xl_op._smoother.value_weight(t, xl_op._param[2])[0])

      xl_op.set_time_point(t)
      an_ds_dp = xl_op.get_ds_dp()
      fd_ds_dp = get_fd_gradients(xl_op, [1.e-6 * pi/180] * num_param)
      #print t
      #print "Gradients:"
      #for s, a, f in zip(param_names, an_ds_dp, fd_ds_dp):
      #    print s
      #    print a
      #    print f
      #    print "diff:", a-f
      #    print
      #
      for e, f in zip(an_ds_dp, fd_ds_dp):
        assert(approx_equal((e - f), null_mat, eps = 1.e-6))

    if self.do_plots:
      try:
        import matplotlib.pyplot as plt
        plt.ion()
        plt.clf()
        plt.subplot(311)
        plt.cla()
        plt.scatter(smooth_at, phi1_data)
        plt.title("Phi1")
        plt.xlabel("image number")
        plt.ylabel("Phi1 (mrad)")
        plt.subplot(312)
        plt.cla()
        plt.scatter(smooth_at, phi2_data)
        plt.title("Phi2")
        plt.xlabel("image number")
        plt.ylabel("Phi2 (mrad)")
        plt.subplot(313)
        plt.cla()
        plt.scatter(smooth_at, phi3_data)
        plt.title("Phi3")
        plt.xlabel("image number")
        plt.ylabel("Phi3 (mrad)")
        plt.suptitle("Parameter smoothing with %d intervals" % nintervals)
        plt.draw()
      except ImportError as e:
        print "pyplot not available", e

    print "OK"
コード例 #14
0
def test_ScanVaryingCrystalOrientationParameterisation_intervals(
        nintervals, plots=False):
    """Test a ScanVaryingCrystalOrientationParameterisation with
    a range of different numbers of intervals"""

    vmp = _TestScanVaryingModelParameterisation()

    # Parameterise the crystal with the image range and five intervals. Init
    # TestOrientationModel to explore gradients at image 50, but actually
    # will try various time points in the test
    xl_op = _TestOrientationModel(50, vmp.xl, vmp.image_range, nintervals)

    # How many parameters?
    num_param = xl_op.num_free()

    # shift the parameters away from zero
    p_vals = xl_op.get_param_vals()
    sigmas = [1.0] * len(p_vals)
    new_vals = random_param_shift(p_vals, sigmas)
    xl_op.set_param_vals(new_vals)

    # recalc state and gradients at image 50
    xl_op.compose()
    p_vals = xl_op.get_param_vals()
    # print "Shifted parameter vals", p_vals

    # compare analytical and finite difference derivatives at image 50
    an_ds_dp = xl_op.get_ds_dp()
    fd_ds_dp = get_fd_gradients(xl_op, [1.0e-6 * math.pi / 180] * num_param)

    null_mat = matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0))
    for e, f in zip(an_ds_dp, fd_ds_dp):
        assert approx_equal((e - f), null_mat, eps=1.0e-6)

    # Now test gradients at equally spaced time points across the whole
    # range
    num_points = 50
    smooth_at = []
    phi1_data = []
    phi2_data = []
    phi3_data = []
    step_size = (vmp.image_range[1] - vmp.image_range[0]) / num_points
    for t in [
            vmp.image_range[0] + e * step_size for e in range(num_points + 1)
    ]:

        # collect data for plot
        smooth_at.append(t)
        phi1_data.append(xl_op._smoother.value_weight(t, xl_op._param[0])[0])
        phi2_data.append(xl_op._smoother.value_weight(t, xl_op._param[1])[0])
        phi3_data.append(xl_op._smoother.value_weight(t, xl_op._param[2])[0])

        xl_op.set_time_point(t)
        an_ds_dp = xl_op.get_ds_dp()
        fd_ds_dp = get_fd_gradients(xl_op,
                                    [1.0e-6 * math.pi / 180] * num_param)
        for e, f in zip(an_ds_dp, fd_ds_dp):
            assert approx_equal((e - f), null_mat, eps=1.0e-6)

    if plots:
        import matplotlib.pyplot as plt

        plt.ion()
        plt.clf()
        plt.subplot(311)
        plt.cla()
        plt.scatter(smooth_at, phi1_data)
        plt.title("Phi1")
        plt.xlabel("image number")
        plt.ylabel("Phi1 (mrad)")
        plt.subplot(312)
        plt.cla()
        plt.scatter(smooth_at, phi2_data)
        plt.title("Phi2")
        plt.xlabel("image number")
        plt.ylabel("Phi2 (mrad)")
        plt.subplot(313)
        plt.cla()
        plt.scatter(smooth_at, phi3_data)
        plt.title("Phi3")
        plt.xlabel("image number")
        plt.ylabel("Phi3 (mrad)")
        plt.suptitle("Parameter smoothing with %d intervals" % nintervals)
        plt.draw()
コード例 #15
0
    # Now using parameterisation in mrad

    # random initial orientations with a random parameter shift at each
    attempts = 100
    failures = 0
    for i in range(attempts):

        # create random initial position
        det = Detector(random_panel())
        dp = DetectorParameterisationSinglePanel(det)

        # apply a random parameter shift
        p_vals = dp.get_param_vals()
        p_vals = random_param_shift(
            p_vals,
            [10, 10, 10, 1000. * pi / 18, 1000. * pi / 18, 1000. * pi / 18])
        dp.set_param_vals(p_vals)

        # obtain current sensor state
        #state = dp.get_state()

        # compare analytical and finite difference derivatives.
        an_ds_dp = dp.get_ds_dp(multi_state_elt=0)
        fd_ds_dp = get_fd_gradients(dp, [1.e-6] * 3 + [1.e-4 * pi / 180] * 3)

        for j in range(6):
            try:
                assert (approx_equal((fd_ds_dp[j] - an_ds_dp[j]),
                                     matrix.sqr(
                                         (0., 0., 0., 0., 0., 0., 0., 0., 0.)),
コード例 #16
0
def test():
    import random
    import textwrap

    from cctbx.uctbx import unit_cell
    from libtbx.test_utils import approx_equal

    def random_direction_close_to(vector):
        return vector.rotate_around_origin(
            matrix.col((random.random(), random.random(),
                        random.random())).normalize(),
            random.gauss(0, 1.0),
            deg=True,
        )

    # make a random P1 crystal and parameterise it
    a = random.uniform(10, 50) * random_direction_close_to(
        matrix.col((1, 0, 0)))
    b = random.uniform(10, 50) * random_direction_close_to(
        matrix.col((0, 1, 0)))
    c = random.uniform(10, 50) * random_direction_close_to(
        matrix.col((0, 0, 1)))
    xl = Crystal(a, b, c, space_group_symbol="P 1")

    xl_op = CrystalOrientationParameterisation(xl)
    xl_ucp = CrystalUnitCellParameterisation(xl)

    null_mat = matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0))

    # compare analytical and finite difference derivatives
    an_ds_dp = xl_op.get_ds_dp()
    fd_ds_dp = get_fd_gradients(xl_op, [1.0e-6 * pi / 180] * 3)
    for e, f in zip(an_ds_dp, fd_ds_dp):
        assert approx_equal((e - f), null_mat, eps=1.0e-6)

    an_ds_dp = xl_ucp.get_ds_dp()
    fd_ds_dp = get_fd_gradients(xl_ucp, [1.0e-7] * xl_ucp.num_free())
    for e, f in zip(an_ds_dp, fd_ds_dp):
        assert approx_equal((e - f), null_mat, eps=1.0e-6)

    # random initial orientations with a random parameter shift at each
    attempts = 100
    for i in range(attempts):

        # make a random P1 crystal and parameterise it
        a = random.uniform(10, 50) * random_direction_close_to(
            matrix.col((1, 0, 0)))
        b = random.uniform(10, 50) * random_direction_close_to(
            matrix.col((0, 1, 0)))
        c = random.uniform(10, 50) * random_direction_close_to(
            matrix.col((0, 0, 1)))
        xl = Crystal(a, b, c, space_group_symbol="P 1")
        xl_op = CrystalOrientationParameterisation(xl)
        xl_uc = CrystalUnitCellParameterisation(xl)

        # apply a random parameter shift to the orientation
        p_vals = xl_op.get_param_vals()
        p_vals = random_param_shift(
            p_vals, [1000 * pi / 9, 1000 * pi / 9, 1000 * pi / 9])
        xl_op.set_param_vals(p_vals)

        # compare analytical and finite difference derivatives
        xl_op_an_ds_dp = xl_op.get_ds_dp()
        xl_op_fd_ds_dp = get_fd_gradients(xl_op, [1.0e-5 * pi / 180] * 3)

        # apply a random parameter shift to the unit cell. We have to
        # do this in a way that is respectful to metrical constraints,
        # so don't modify the parameters directly; modify the cell
        # constants and extract the new parameters
        cell_params = xl.get_unit_cell().parameters()
        cell_params = random_param_shift(cell_params, [1.0] * 6)
        new_uc = unit_cell(cell_params)
        newB = matrix.sqr(new_uc.fractionalization_matrix()).transpose()
        S = symmetrize_reduce_enlarge(xl.get_space_group())
        S.set_orientation(orientation=newB)
        X = S.forward_independent_parameters()
        xl_uc.set_param_vals(X)

        xl_uc_an_ds_dp = xl_ucp.get_ds_dp()

        # now doing finite differences about each parameter in turn
        xl_uc_fd_ds_dp = get_fd_gradients(xl_ucp, [1.0e-7] * xl_ucp.num_free())

        for j in range(3):
            assert approx_equal((xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j]),
                                null_mat,
                                eps=1.0e-6), textwrap.dedent("""\
        Failure in try {i}
        failure for parameter number {j}
        of the orientation parameterisation
        with fd_ds_dp =
        {fd}
        and an_ds_dp =
        {an}
        so that difference fd_ds_dp - an_ds_dp =
        {diff}
        """).format(
                                    i=i,
                                    j=j,
                                    fd=xl_op_fd_ds_dp[j],
                                    an=xl_op_an_ds_dp[j],
                                    diff=xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j],
                                )

        for j in range(xl_ucp.num_free()):
            assert approx_equal((xl_uc_fd_ds_dp[j] - xl_uc_an_ds_dp[j]),
                                null_mat,
                                eps=1.0e-6), textwrap.dedent("""\
        Failure in try {i}
        failure for parameter number {j}
        of the unit cell parameterisation
        with fd_ds_dp =
        {fd}
        and an_ds_dp =
        {an}
        so that difference fd_ds_dp - an_ds_dp =
        {diff}
        """).format(
                                    i=i,
                                    j=j,
                                    fd=xl_uc_fd_ds_dp[j],
                                    an=xl_uc_an_ds_dp[j],
                                    diff=xl_uc_fd_ds_dp[j] - xl_uc_an_ds_dp[j],
                                )
コード例 #17
0
  def test_num_intervals(self, nintervals):
    """Test a range of different numbers of intervals"""

    # Parameterise the crystal with the image range and five intervals. Init
    # TestOrientationModel to explore gradients at image 50, but actually
    # will try various time points in the test
    xl_op = TestOrientationModel(50, self.xl, self.image_range, nintervals)

    # How many parameters?
    num_param = xl_op.num_free()

    # shift the parameters away from zero
    p_vals = xl_op.get_param_vals()
    sigmas = [1.0] * len(p_vals)
    new_vals = random_param_shift(p_vals, sigmas)
    xl_op.set_param_vals(new_vals)

    # recalc state and gradients at image 50
    xl_op.compose()
    p_vals = xl_op.get_param_vals()
    #print "Shifted parameter vals", p_vals

    # compare analytical and finite difference derivatives at image 50
    an_ds_dp = xl_op.get_ds_dp()
    fd_ds_dp = get_fd_gradients(xl_op, [1.e-6 * pi/180] * num_param)
    param_names = xl_op.get_param_names()

    null_mat = matrix.sqr((0., 0., 0., 0., 0., 0., 0., 0., 0.))
    for e, f in zip(an_ds_dp, fd_ds_dp):
      assert(approx_equal((e - f), null_mat, eps = 1.e-6))

    # Now test gradients at equally spaced time points across the whole
    # range
    num_points = 50
    smooth_at = []
    phi1_data = []
    phi2_data = []
    phi3_data = []
    step_size = (self.image_range[1] - self.image_range[0]) / num_points
    for t in [self.image_range[0] + e * step_size \
                for e in range(num_points + 1)]:

      # collect data for plot
      smooth_at.append(t)
      phi1_data.append(xl_op._smoother.value_weight(t, xl_op._param[0])[0])
      phi2_data.append(xl_op._smoother.value_weight(t, xl_op._param[1])[0])
      phi3_data.append(xl_op._smoother.value_weight(t, xl_op._param[2])[0])

      xl_op.set_time_point(t)
      an_ds_dp = xl_op.get_ds_dp()
      fd_ds_dp = get_fd_gradients(xl_op, [1.e-6 * pi/180] * num_param)
      #print t
      #print "Gradients:"
      #for s, a, f in zip(param_names, an_ds_dp, fd_ds_dp):
      #    print s
      #    print a
      #    print f
      #    print "diff:", a-f
      #    print
      #
      for e, f in zip(an_ds_dp, fd_ds_dp):
        assert(approx_equal((e - f), null_mat, eps = 1.e-6))

    if self.do_plots:
      try:
        import matplotlib.pyplot as plt
        plt.ion()
        plt.clf()
        plt.subplot(311)
        plt.cla()
        plt.scatter(smooth_at, phi1_data)
        plt.title("Phi1")
        plt.xlabel("image number")
        plt.ylabel("Phi1 (mrad)")
        plt.subplot(312)
        plt.cla()
        plt.scatter(smooth_at, phi2_data)
        plt.title("Phi2")
        plt.xlabel("image number")
        plt.ylabel("Phi2 (mrad)")
        plt.subplot(313)
        plt.cla()
        plt.scatter(smooth_at, phi3_data)
        plt.title("Phi3")
        plt.xlabel("image number")
        plt.ylabel("Phi3 (mrad)")
        plt.suptitle("Parameter smoothing with %d intervals" % nintervals)
        plt.draw()
      except ImportError as e:
        print "pyplot not available", e

    print "OK"
コード例 #18
0
  assert(approx_equal(matrix.col(s0.get_s0()).angle(s0_old), 0.1413033))
  assert(approx_equal(matrix.col(s0.get_s0()).length(), 0.8))

  # random initial orientations and wavelengths with a random parameter shifts
  attempts = 1000
  failures = 0
  for i in range(attempts):

    # make a random beam vector and parameterise it
    s0 = bf.make_beam(matrix.col.random(3, 0.5, 1.5),
                      wavelength=random.uniform(0.8,1.5))
    s0p = BeamParameterisation(s0)

    # apply a random parameter shift
    p_vals = s0p.get_param_vals()
    p_vals = random_param_shift(p_vals, [1000*pi/9, 1000*pi/9, 0.01])
    s0p.set_param_vals(p_vals)

    # compare analytical and finite difference derivatives
    an_ds_dp = s0p.get_ds_dp()
    fd_ds_dp = get_fd_gradients(s0p, [1.e-5 * pi/180, 1.e-5 * pi/180, 1.e-6])

    for j in range(3):
      try:
        assert(approx_equal((fd_ds_dp[j] - an_ds_dp[j]),
                matrix.col((0., 0., 0.)), eps = 1.e-6))
      except Exception:
        failures += 1
        print "for try", i
        print "failure for parameter number", j
        print "with fd_ds_dp = "
コード例 #19
0
# Create parameterisations of these models, with 5 samples for the
# scan-varying crystal parameterisations

det_param = DetectorParameterisationSinglePanel(mydetector)
s0_param = BeamParameterisation(mybeam, mygonio)
xlo_param = ScanVaryingCrystalOrientationParameterisation(
        mycrystal, myscan.get_array_range(), 5)
xluc_param = ScanVaryingCrystalUnitCellParameterisation(
        mycrystal, myscan.get_array_range(), 5)

#### Cause the crystal U and B to vary over the scan

# Vary orientation angles by ~1.0 mrad each checkpoint
p_vals = xlo_param.get_param_vals()
sigmas = [1.0] * len(p_vals)
new_vals = random_param_shift(p_vals, sigmas)
xlo_param.set_param_vals(new_vals)

# Vary unit cell parameters, on order of 1% of the initial metrical
# matrix parameters
p_vals = xluc_param.get_param_vals()
sigmas = [0.01 * p for p in p_vals]
new_vals = random_param_shift(p_vals, sigmas)
xluc_param.set_param_vals(new_vals)

# Generate an ExperimentList
experiments = ExperimentList()
experiments.append(Experiment(
      beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan,
      crystal=mycrystal, imageset=None))
sweep_range = myscan.get_oscillation_range(deg=False)
コード例 #20
0
  # 5. Tests of the calculation of derivatives

  # Now using parameterisation in mrad

  # random initial orientations with a random parameter shift at each
  attempts = 100
  failures = 0
  for i in range(attempts):

    # create random initial position
    det = Detector(random_panel())
    dp = DetectorParameterisationSinglePanel(det)

    # apply a random parameter shift
    p_vals = dp.get_param_vals()
    p_vals = random_param_shift(p_vals, [10, 10, 10, 1000.*pi/18,
                                         1000.*pi/18, 1000.*pi/18])
    dp.set_param_vals(p_vals)

    # obtain current sensor state
    #state = dp.get_state()

    # compare analytical and finite difference derivatives.
    an_ds_dp = dp.get_ds_dp(multi_state_elt=0)
    fd_ds_dp = get_fd_gradients(dp,
                    [1.e-6] * 3 + [1.e-4 * pi/180] * 3)

    for j in range(6):
      try:
        assert(approx_equal((fd_ds_dp[j] - an_ds_dp[j]),
                matrix.sqr((0., 0., 0.,
                            0., 0., 0.,
コード例 #21
0
def test():
    # set the random seed to make the test reproducible
    random.seed(1337)

    # set up a simple detector frame with directions aligned with
    # principal axes and sensor origin located on the z-axis at -110
    d1 = matrix.col((1, 0, 0))
    d2 = matrix.col((0, -1, 0))
    # lim = (0,50)
    npx_fast = 1475
    npx_slow = 1679
    pix_size_f = pix_size_s = 0.172
    detector = DetectorFactory.make_detector(
        "PAD",
        d1,
        d2,
        matrix.col((0, 0, -110)),
        (pix_size_f, pix_size_s),
        (npx_fast, npx_slow),
        (0, 2e20),
    )

    dp = DetectorParameterisationSinglePanel(detector)
    beam = BeamFactory().make_beam(
        sample_to_source=-1 * (matrix.col((0, 0, -110)) + 10 * d1 + 10 * d2),
        wavelength=1.0,
    )

    # Test change of parameters
    # =========================

    # 1. shift detector plane so that the z-axis intercepts its centre
    # at a distance of 100 along the initial normal direction. As the
    # initial normal is along -z, we expect the frame to intercept the
    # z-axis at -100.

    p_vals = dp.get_param_vals()
    p_vals[0:3] = [100.0, 0.0, 0.0]
    dp.set_param_vals(p_vals)
    detector = dp._model
    assert len(detector) == 1
    panel = detector[0]
    v1 = matrix.col(panel.get_origin())
    v2 = matrix.col((0.0, 0.0, 1.0))
    assert approx_equal(v1.dot(v2), -100.0)

    # 2. rotate frame around its initial normal by +90 degrees. Only d1
    # and d2 should change. As we rotate clockwise around the initial
    # normal (-z direction) then d1 should rotate onto the original
    # direction d2, and d2 should rotate to negative of the original
    # direction d1

    p_vals[3] = 1000.0 * pi / 2  # set tau1 value
    dp.set_param_vals(p_vals)

    detector = dp._model
    assert len(detector) == 1
    panel = detector[0]
    assert approx_equal(
        matrix.col(panel.get_fast_axis()).dot(dp._initial_state["d1"]), 0.0)
    assert approx_equal(
        matrix.col(panel.get_slow_axis()).dot(dp._initial_state["d2"]), 0.0)
    assert approx_equal(
        matrix.col(panel.get_normal()).dot(dp._initial_state["dn"]), 1.0)

    # 3. no rotation around initial normal, +10 degrees around initial
    # d1 direction and +10 degrees around initial d2. Check d1 and d2
    # match paper calculation

    p_vals[3] = 0.0  # tau1
    p_vals[4] = 1000.0 * pi / 18  # tau2
    p_vals[5] = 1000.0 * pi / 18  # tau3
    dp.set_param_vals(p_vals)

    # paper calculation values
    v1 = matrix.col((cos(pi / 18), 0, sin(pi / 18)))
    v2 = matrix.col((
        sin(pi / 18)**2,
        -cos(pi / 18),
        sqrt((2 * sin(pi / 36) * sin(pi / 18))**2 - sin(pi / 18)**4) -
        sin(pi / 18),
    ))

    detector = dp._model
    assert len(detector) == 1
    panel = detector[0]
    assert approx_equal(matrix.col(panel.get_fast_axis()).dot(v1), 1.0)
    assert approx_equal(matrix.col(panel.get_slow_axis()).dot(v2), 1.0)

    # 4. Test fixing and unfixing of parameters
    p_vals = [
        100.0, 0.0, 0.0, 1000.0 * pi / 18, 1000.0 * pi / 18, 1000.0 * pi / 18
    ]
    dp.set_param_vals(p_vals)
    f = dp.get_fixed()
    f[0:3] = [True] * 3
    dp.set_fixed(f)
    p_vals2 = [0.0, 0.0, 0.0]
    dp.set_param_vals(p_vals2)
    assert dp.get_param_vals(only_free=False) == [
        100.0, 0.0, 0.0, 0.0, 0.0, 0.0
    ]

    an_ds_dp = dp.get_ds_dp()
    assert len(an_ds_dp) == 3

    f[0:3] = [False] * 3
    dp.set_fixed(f)
    p_vals = dp.get_param_vals()
    p_vals2 = [a + b for a, b in zip(p_vals, [-10.0, 1.0, 1.0, 0.0, 0.0, 0.0])]
    dp.set_param_vals(p_vals2)
    assert dp.get_param_vals() == [90.0, 1.0, 1.0, 0.0, 0.0, 0.0]

    # 5. Tests of the calculation of derivatives

    # Now using parameterisation in mrad

    # random initial orientations with a random parameter shift at each
    attempts = 100
    for i in range(attempts):

        # create random initial position
        det = Detector(random_panel())
        dp = DetectorParameterisationSinglePanel(det)

        # apply a random parameter shift
        p_vals = dp.get_param_vals()
        p_vals = random_param_shift(
            p_vals,
            [10, 10, 10, 1000.0 * pi / 18, 1000.0 * pi / 18, 1000.0 * pi / 18])
        dp.set_param_vals(p_vals)

        # compare analytical and finite difference derivatives.
        an_ds_dp = dp.get_ds_dp(multi_state_elt=0)
        fd_ds_dp = get_fd_gradients(dp, [1.0e-6] * 3 + [1.0e-4 * pi / 180] * 3)

        for j in range(6):
            assert approx_equal(
                (fd_ds_dp[j] - an_ds_dp[j]),
                matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)),
                eps=1.0e-6,
            ), textwrap.dedent("""\
        Failure comparing analytical with finite difference derivatives.
        Failure in try {i}
        failure for parameter number {j}
        of the orientation parameterisation
        with fd_ds_dp =
        {fd}
        and an_ds_dp =
        {an}
        so that difference fd_ds_dp - an_ds_dp =
        {diff}
        """).format(i=i,
                    j=j,
                    fd=fd_ds_dp[j],
                    an=an_ds_dp[j],
                    diff=fd_ds_dp[j] - an_ds_dp[j])

    # 5. Test a multi-panel detector with non-coplanar panels.

    # place a beam at the centre of the single panel detector (need a
    # beam to initialise the multi-panel detector parameterisation)
    lim = det[0].get_image_size_mm()
    shift1 = lim[0] / 2.0
    shift2 = lim[1] / 2.0
    beam_centre = (matrix.col(det[0].get_origin()) +
                   shift1 * matrix.col(det[0].get_fast_axis()) +
                   shift2 * matrix.col(det[0].get_slow_axis()))
    beam = BeamFactory().make_beam(sample_to_source=-1.0 * beam_centre,
                                   wavelength=1.0)

    multi_panel_detector = make_multi_panel(det)

    # parameterise this detector
    dp = DetectorParameterisationMultiPanel(multi_panel_detector, beam)

    # ensure the beam still intersects the central panel
    intersection = multi_panel_detector.get_ray_intersection(beam.get_s0())
    assert intersection[0] == 4

    # record the offsets and dir1s, dir2s
    offsets_before_shift = dp._offsets
    dir1s_before_shift = dp._dir1s
    dir2s_before_shift = dp._dir2s

    # apply a random parameter shift (~10 mm distances, ~50 mrad angles)
    p_vals = dp.get_param_vals()
    p_vals = random_param_shift(p_vals, [10, 10, 10, 50, 50, 50])

    # reparameterise the detector
    dp = DetectorParameterisationMultiPanel(multi_panel_detector, beam)

    # record the offsets and dir1s, dir2s
    offsets_after_shift = dp._offsets
    dir1s_after_shift = dp._dir1s
    dir2s_after_shift = dp._dir2s

    # ensure the offsets, dir1s and dir2s are the same. This means that
    # each panel in the detector moved with the others as a rigid body
    for a, b in zip(offsets_before_shift, offsets_after_shift):
        assert approx_equal(a, b, eps=1.0e-10)

    for a, b in zip(dir1s_before_shift, dir1s_after_shift):
        assert approx_equal(a, b, eps=1.0e-10)

    for a, b in zip(dir2s_before_shift, dir2s_after_shift):
        assert approx_equal(a, b, eps=1.0e-10)

    attempts = 5
    for i in range(attempts):

        multi_panel_detector = make_multi_panel(det)

        # parameterise this detector
        dp = DetectorParameterisationMultiPanel(multi_panel_detector, beam)
        p_vals = dp.get_param_vals()

        # apply a random parameter shift
        p_vals = random_param_shift(
            p_vals,
            [10, 10, 10, 1000.0 * pi / 18, 1000.0 * pi / 18, 1000.0 * pi / 18])
        dp.set_param_vals(p_vals)

        # compare analytical and finite difference derivatives
        # get_fd_gradients will implicitly only get gradients for the
        # 1st panel in the detector, so explicitly get the same for the
        # analytical gradients

        for j in range(9):

            an_ds_dp = dp.get_ds_dp(multi_state_elt=j)
            fd_ds_dp = get_fd_gradients(dp, [1.0e-7] * dp.num_free(),
                                        multi_state_elt=j)

            for k in range(6):
                assert approx_equal(
                    (fd_ds_dp[k] - matrix.sqr(an_ds_dp[k])),
                    matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)),
                    eps=1.0e-5,
                    out=None,
                ), textwrap.dedent("""\
        Failure comparing analytical with finite difference derivatives.
        Failure in try {i}
        for panel number {j]
        failure for parameter number {k}
        of the orientation parameterisation
        with fd_ds_dp =
        {fd}
        and an_ds_dp =
        {an}
        so that difference fd_ds_dp - an_ds_dp =
        {diff}
        """).format(
                    i=i,
                    j=j,
                    k=k,
                    fd=fd_ds_dp[k],
                    an=an_ds_dp[k],
                    diff=fd_ds_dp[k] - matrix.sqr(an_ds_dp[k]),
                )
コード例 #22
0
def test_beam_parameters():
    from dxtbx.model import BeamFactory

    from dials.algorithms.refinement.parameterisation.beam_parameters import (
        BeamParameterisation,
    )
    from dials.algorithms.refinement.refinement_helpers import (
        get_fd_gradients,
        random_param_shift,
    )

    # make a random beam vector and parameterise it
    bf = BeamFactory()
    s0 = bf.make_beam(matrix.col.random(3, 0.5, 1.5), wavelength=1.2)
    s0p = BeamParameterisation(s0)

    # Let's do some basic tests. First, can we change parameter values and
    # update the modelled vector s0?
    s0_old = matrix.col(s0.get_s0())
    s0p.set_param_vals([1000 * 0.1, 1000 * 0.1, 0.8])
    assert matrix.col(s0.get_s0()).angle(s0_old) == pytest.approx(0.1413033, abs=1e-6)
    assert matrix.col(s0.get_s0()).length() == pytest.approx(0.8, abs=1e-6)

    # random initial orientations and wavelengths with a random parameter shifts
    attempts = 1000
    for i in range(attempts):

        # make a random beam vector and parameterise it
        sample_to_source = matrix.col.random(3, 0.5, 1.5).normalize()
        beam = bf.make_beam(sample_to_source, wavelength=random.uniform(0.8, 1.5))
        # Ensure consistent polarization (https://github.com/cctbx/dxtbx/issues/454)
        beam.set_polarization_normal(sample_to_source.ortho().normalize())

        s0p = BeamParameterisation(beam)

        # apply a random parameter shift
        p_vals = s0p.get_param_vals()
        p_vals = random_param_shift(p_vals, [1000 * pi / 9, 1000 * pi / 9, 0.01])
        s0p.set_param_vals(p_vals)

        # compare analytical and finite difference derivatives
        an_ds_dp = s0p.get_ds_dp()
        fd_ds_dp = get_fd_gradients(s0p, [1.0e-5 * pi / 180, 1.0e-5 * pi / 180, 1.0e-6])

        for j in range(3):
            try:
                assert list(fd_ds_dp[j] - an_ds_dp[j]) == pytest.approx(
                    (0, 0, 0), abs=1e-6
                )
            except Exception:
                print("for try", i)
                print("failure for parameter number", j)
                print("with fd_ds_dp = ")
                print(fd_ds_dp[j])
                print("and an_ds_dp = ")
                print(an_ds_dp[j])
                print("so that difference fd_ds_dp - an_ds_dp =")
                print(fd_ds_dp[j] - an_ds_dp[j])
                raise

        # Ensure the polarization normal vector remains orthogonal to the beam
        # (https://github.com/dials/dials/issues/1939)
        assert (
            abs(
                matrix.col(beam.get_unit_s0()).dot(
                    matrix.col(beam.get_polarization_normal())
                )
            )
            < 1e-10
        )