def __init__(self, phi0, misset0, phi1, misset1): """Initialise the rotation axis and what have you from some experimental results. N.B. all input values in DEGREES.""" # canonical: X = X-ray beam # Z = rotation axis # Y = Z ^ X z = matrix.col([0, 0, 1]) # then calculate the rotation axis R = ( ( z.axis_and_angle_as_r3_rotation_matrix(phi1, deg=True) * matrix.sqr(xyz_matrix(misset1[0], misset1[1], misset1[2])) ) * ( z.axis_and_angle_as_r3_rotation_matrix(phi0, deg=True) * matrix.sqr(xyz_matrix(misset0[0], misset0[1], misset0[2])) ).inverse() ) self._z = z self._r = matrix.col(r3_rotation_axis_and_angle_from_matrix(R).axis) self._M0 = matrix.sqr(xyz_matrix(misset0[0], misset0[1], misset0[2])) return
def run(self, args=None): """Execute the script.""" # Parse the command line params, options = self.parser.parse_args(args, show_diff_phil=True) # Check the number of experiments is at least 2 experiments = flatten_experiments(params.input.experiments) if len(experiments) < 2: self.parser.print_help() return detectors = [experiment.detector[0] for experiment in experiments] for pair in combinations(detectors, 2): determine_axis(pair, params) crystals = [experiment.crystal for experiment in experiments] goniometers = [experiment.goniometer for experiment in experiments] FUs = [] for c, g in zip(crystals, goniometers): u = matrix.sqr(c.get_U()) f = matrix.sqr(g.get_fixed_rotation()) FUs.append(f * u) for pair in combinations(FUs, 2): R = pair[1] * pair[0].inverse() rot = r3_rotation_axis_and_angle_from_matrix(R) angle = rot.angle(deg=True) axis = matrix.col(rot.axis) if abs(angle) < 10: continue print("Axis: %8.5f %8.5f %8.5f" % axis.elems, "angle: %7.4f" % angle)
def difference_rotation_matrix_axis_angle(crystal_a, crystal_b, target_angle=0): from cctbx import sgtbx # assert crystal_a.get_space_group() == crystal_b.get_space_group() space_group = crystal_b.get_space_group() best_R_ab = None best_cb_op = None best_axis = None best_angle = 1e8 # iterate over space group ops to find smallest differences for i_op, op in enumerate(space_group.build_derived_laue_group().all_ops()): if op.r().determinant() < 0: continue elif not op.t().is_zero(): continue cb_op = sgtbx.change_of_basis_op(op.inverse()) crystal_b_sym = crystal_b.change_basis(cb_op) U_a = crystal_a.get_U() U_b = crystal_b_sym.get_U() assert U_a.is_r3_rotation_matrix() assert U_b.is_r3_rotation_matrix() # the rotation matrix to transform from U_a to U_b R_ab = U_b * U_a.transpose() axis_angle = r3_rotation_axis_and_angle_from_matrix(R_ab) axis = axis_angle.axis angle = axis_angle.angle() * 180.0 / math.pi for sign in (+1, -1): if abs(sign * angle - target_angle) < abs(best_angle - target_angle): best_angle = sign * angle best_axis = tuple(sign * a for a in axis) best_R_ab = R_ab if sign > 0 else R_ab.inverse() best_cb_op = cb_op if sign > 0 else cb_op.inverse() return best_R_ab, best_axis, best_angle, best_cb_op
def difference_rotation_matrix_axis_angle(crystal_a, crystal_b, target_angle=0): from cctbx import sgtbx # assert crystal_a.get_space_group() == crystal_b.get_space_group() space_group = crystal_b.get_space_group() best_R_ab = None best_cb_op = None best_axis = None best_angle = 1e8 # iterate over space group ops to find smallest differences for i_op, op in enumerate(space_group.build_derived_laue_group().all_ops()): if op.r().determinant() < 0: continue elif not op.t().is_zero(): continue cb_op = sgtbx.change_of_basis_op(op.inverse()) crystal_b_sym = crystal_b.change_basis(cb_op) U_a = matrix.sqr(crystal_a.get_U()) U_b = matrix.sqr(crystal_b_sym.get_U()) assert U_a.is_r3_rotation_matrix() assert U_b.is_r3_rotation_matrix() # the rotation matrix to transform from U_a to U_b R_ab = U_b * U_a.transpose() axis_angle = r3_rotation_axis_and_angle_from_matrix(R_ab) axis = axis_angle.axis angle = axis_angle.angle() * 180.0 / math.pi for sign in (+1, -1): if abs(sign * angle - target_angle) < abs(best_angle - target_angle): best_angle = sign * angle best_axis = tuple(sign * a for a in axis) best_R_ab = R_ab if sign > 0 else R_ab.inverse() best_cb_op = cb_op if sign > 0 else cb_op.inverse() return best_R_ab, best_axis, best_angle, best_cb_op
def compute_Q(xparm_target, xparm_move): _M = determine_rotation_to_dtrek(xparm_target) a_t, b_t, c_t = parse_xds_xparm(xparm_target) a_m, b_m, c_m = parse_xds_xparm(xparm_move) m_t = matrix.sqr(a_t + b_t + c_t) min_r = 180.0 min_ax = None for op in ['X,Y,Z', '-X,-Y,Z', '-X,Y,-Z', 'X,-Y,-Z', 'Z,X,Y', 'Z,-X,-Y', '-Z,-X,Y', '-Z,X,-Y', 'Y,Z,X', '-Y,Z,-X', 'Y,-Z,-X', '-Y,-Z,X']: op_m = op_to_mat(op) m_m = op_m * matrix.sqr(a_m + b_m + c_m) q = m_t.inverse() * m_m if math.fabs(q.determinant() - 1) > 0.1: print 'rejected %s' % op continue q_r = r3_rotation_axis_and_angle_from_matrix(q.inverse()) if math.fabs(q_r.angle(deg = True)) < min_r: if q_r.angle(deg = True) >= 0: min_ax = matrix.col(q_r.axis) min_r = q_r.angle(deg = True) else: min_ax = - matrix.col(q_r.axis) min_r = - q_r.angle(deg = True) return (_M * min_ax).elems, min_r
def _reorient_coordinate_frame(self): """Align a DIALS experiment and data in a reflection table to the PETS coordinate system. In that system, the s0 vector is aligned with -Z, while the rotation axis is in the X-Z plane, close to +X""" axis = matrix.col(self.experiment.goniometer.get_rotation_axis()) us0 = matrix.col(self.experiment.beam.get_unit_s0()) normal = us0.cross(-axis).normalize() orthogonalised_axis = us0.cross(normal).normalize() # Keep track of s1.us0 values to check reorientation s1_dot_us0 = self.reflections["s1"].dot(us0) R = align_reference_frame(us0, (0, 0, -1), orthogonalised_axis, (1, 0, 0)) axis_angle = r3_rotation_axis_and_angle_from_matrix(R) axis = axis_angle.axis angle = axis_angle.angle(deg=False) logger.info( "Rotating experiment about axis ({:.4f}, {:.4f}, {:.4f}) by {:.3f}°" .format(*axis, np.degrees(angle))) self.experiment.detector.rotate_around_origin(axis, angle, deg=False) self.experiment.crystal = rotate_crystal(self.experiment.crystal, R, axis, angle) # Following does not work (https://github.com/cctbx/dxtbx/issues/454) # self.experiment.beam.rotate_around_origin(axis, angle, deg=False) # Set unit s0 and polarization normal directly instead (preserving inconsistent # beam, if that's what we have). new_us0 = (R * matrix.col(self.experiment.beam.get_unit_s0())).normalize() new_p_norm = (R * matrix.col( self.experiment.beam.get_polarization_normal())).normalize() self.experiment.beam.set_unit_s0(new_us0) self.experiment.beam.set_polarization_normal(new_p_norm) # Rotating the goniometer is also complicated. See https://github.com/cctbx/dxtbx/pull/451 new_datum = (R * matrix.col( self.experiment.goniometer.get_rotation_axis_datum())).normalize() new_F = (R * matrix.sqr(self.experiment.goniometer.get_fixed_rotation()) * R.transpose()) new_S = ( R * matrix.sqr(self.experiment.goniometer.get_setting_rotation()) * R.transpose()) self.experiment.goniometer.set_rotation_axis_datum(new_datum) self.experiment.goniometer.set_setting_rotation(new_S) self.experiment.goniometer.set_fixed_rotation(new_F) # Re-calculate s1 vectors and reciprocal lattice points with new geometry el = ExperimentList() el.append(self.experiment) self.reflections.map_centroids_to_reciprocal_space(el, calculated=True) error = flex.abs(s1_dot_us0 - self.reflections["s1"].dot(new_us0)) if flex.max(error) > 1e-10: raise RuntimeError("Failed to rotate experiment correctly")
def derive_axis_angle(xparm0, xparm1): xparm0 = find_xparm(xparm0) xparm1 = find_xparm(xparm1) from scitbx.math import r3_rotation_axis_and_angle_from_matrix import math ub0 = xparm_to_ub(xparm0) ub1 = xparm_to_ub(xparm1) R = ub1 * ub0.inverse() axis_angle = r3_rotation_axis_and_angle_from_matrix(R) axis = axis_angle.axis angle = axis_angle.angle() * 180.0 / math.pi return axis, angle, R
def determine_effective_scan_axis(gonio): x = gonio.rotate_vector(0.0, 1, 0, 0) y = gonio.rotate_vector(0.0, 0, 1, 0) z = gonio.rotate_vector(0.0, 0, 0, 1) R = matrix.rec(x + y + z, (3, 3)).transpose() x1 = gonio.rotate_vector(1.0, 1, 0, 0) y1 = gonio.rotate_vector(1.0, 0, 1, 0) z1 = gonio.rotate_vector(1.0, 0, 0, 1) R1 = matrix.rec(x1 + y1 + z1, (3, 3)).transpose() RA = R1 * R.inverse() rot = r3_rotation_axis_and_angle_from_matrix(RA) return rot.axis, rot.angle(deg = True)
def cbf_gonio_to_effective_axis_fixed_old(cbf_gonio): '''Given a cbf goniometer handle, first determine the real rotation axis, then determine the fixed component of rotation which is rotated about this axis.''' # First construct the real rotation axis, as the difference in rotating # the identity matrix at the end of the scan and the beginning. x = cbf_gonio.rotate_vector(0.0, 1, 0, 0) y = cbf_gonio.rotate_vector(0.0, 0, 1, 0) z = cbf_gonio.rotate_vector(0.0, 0, 0, 1) R = matrix.rec(x + y + z, (3, 3)).transpose() x1 = cbf_gonio.rotate_vector(1.0, 1, 0, 0) y1 = cbf_gonio.rotate_vector(1.0, 0, 1, 0) z1 = cbf_gonio.rotate_vector(1.0, 0, 0, 1) R1 = matrix.rec(x1 + y1 + z1, (3, 3)).transpose() RA = R1 * R.inverse() rot = r3_rotation_axis_and_angle_from_matrix(RA) # Then, given this, determine the component of the scan which is fixed - # which will need to be with respect to the unrotated axis. N.B. this # will not be unique, but should be correct modulo a free rotation about # the shifted axis. start = cbf_gonio.get_rotation_range()[0] # want positive rotations => if negative invert axis axis = matrix.col(rot.axis) angle = rot.angle() if angle < 0: axis = -1 * axis # common sense would suggest in here that if the angle is -ve should # be made +ve - works OK for omega scans but not phi scans, probably # incomplete goniometer definition problem... # start = -start S = axis.axis_and_angle_as_r3_rotation_matrix(start, deg=True) return axis, S.inverse() * R
def run(self): '''Execute the script.''' from dials.util.options import flatten_experiments # Parse the command line params, options = self.parser.parse_args(show_diff_phil=True) # Check the number of experiments is at least 2 experiments = flatten_experiments(params.input.experiments) if len(experiments) < 2: self.parser.print_help() return detectors = [experiment.detector[0] for experiment in experiments] from itertools import combinations for pair in combinations(detectors, 2): determine_axis(pair, params) from scitbx import matrix from scitbx.math import r3_rotation_axis_and_angle_from_matrix crystals = [experiment.crystal for experiment in experiments] goniometers = [experiment.goniometer for experiment in experiments] FUs = [] for c, g in zip(crystals, goniometers): u = matrix.sqr(c.get_U()) f = matrix.sqr(g.get_fixed_rotation()) FUs.append(f * u) for pair in combinations(FUs, 2): R = pair[1] * pair[0].inverse() rot = r3_rotation_axis_and_angle_from_matrix(R) angle = rot.angle(deg=True) axis = matrix.col(rot.axis) if abs(angle) < 10: continue print('Axis: %8.5f %8.5f %8.5f' % axis.elems, 'angle: %7.4f' % angle)
def cbf_gonio_to_effective_axis(cbf_gonio): '''Given a cbf goniometer handle, determine the real rotation axis.''' x = cbf_gonio.rotate_vector(0.0, 1, 0, 0) y = cbf_gonio.rotate_vector(0.0, 0, 1, 0) z = cbf_gonio.rotate_vector(0.0, 0, 0, 1) R = matrix.rec(x + y + z, (3, 3)).transpose() x1 = cbf_gonio.rotate_vector(1.0, 1, 0, 0) y1 = cbf_gonio.rotate_vector(1.0, 0, 1, 0) z1 = cbf_gonio.rotate_vector(1.0, 0, 0, 1) R1 = matrix.rec(x1 + y1 + z1, (3, 3)).transpose() RA = R1 * R.inverse() axis = r3_rotation_axis_and_angle_from_matrix(RA).axis return axis
def align_experiments( experiments: ExperimentList, params: libtbx.phil.scope_extract, ) -> ExperimentList: if len(experiments) > 1: logger.info( "Only the first experiment will be used to determine the detector axes" ) expt = experiments[0] detector = expt.detector if len(detector) > 1: logger.info( "Only the first panel will be used to determine the detector axes") panel = detector[0] xds_x, xds_y = read_xds_inp(params.input.xds_inp) R = align_reference_frame(panel.get_fast_axis(), xds_x, panel.get_slow_axis(), xds_y) axis_angle = r3_rotation_axis_and_angle_from_matrix(R) axis = axis_angle.axis angle = axis_angle.angle() logger.info( f"Rotating experiment{'s' if len(experiments) else ''} about axis {axis} by {np.degrees(angle)}°" ) for expt in experiments: expt.detector.rotate_around_origin(axis, angle, deg=False) expt.beam.rotate_around_origin(axis, angle, deg=False) # https://github.com/cctbx/dxtbx/issues/447 # expt.goniometer.rotate_around_origin(axis, angle, deg=False) rotation_axis = matrix.col(expt.goniometer.get_rotation_axis()) expt.goniometer.set_rotation_axis(R * rotation_axis) if expt.crystal is not None: expt.crystal = rotate_crystal(expt.crystal, R, axis, angle) return experiments
def find_U_matrix(found_vectors, crystal, beam_energy=8, optimise_U=True, refl='orient', angle_accuracy = 0.5): """Given a Crystal class object with a cif file loaded into it, this function returns the U matrix as a dnp array. Args: found_vectors: A list of Vector class objects representing the momentum transfer vectors of the measured Bragg peaks. crystal: A Crystal class object. beam_energy: The beam energy in keV. optimise_U: If True the function optimises the U matrix before returning can be set to False if in Jython because requires scipy. refl: The filter applied to the Bragg reflections read from the cif file. angle_accuracy: The accuracy required for two angle to be considered equal. Returns: U: The U matrix as a dnp object. """ # First gets all the allowed momentum transfer vectors of the crystal. grouped_reflections = f.group_reflections(crystal, beam_energy, refl=refl) all_vectors = [] for group in grouped_reflections: group_vectors = f.momentum_transfer_vectors(group, crystal) all_vectors += group_vectors # Find the target vectors. target_vectors = finding_the_targets(found_vectors, all_vectors, crystal, angle_accuracy) found_vectors_copy = copy.deepcopy(found_vectors) # Find and apply the first rotation. rotation1 = get_rotator(found_vectors[0], target_vectors[0]) found_vectors = rotate_list(rotation1, found_vectors) # Find the second rotation rotation2 = get_second_rotator(target_vectors[0], found_vectors[1], target_vectors[1]) U = rotation2 * rotation1 # Optimising the U matrix def diff(array, data, vectors): """This is a function used to optimise the U matrix. It evaluates the difference between the rotated set of vectors and their corosponding vectors in reciprical space. """ x = array[0] y = array[1] z = array[2] angle = array[3] axis = Vector([x, y, z]) U = Rotator(scm.r3_rotation_axis_and_angle_as_matrix(axis, angle)) data = rotate_list(U, data) index_list=[] for i, dat in enumerate(data): diffs = [] dat = dat for j, vector in enumerate(vectors): diffs.append((dat-vector).length()) index = diffs.index(min(dnp.abs(diffs))) index_list.append(index) targets = [0]*len(data) for i, idx in enumerate(index_list): targets[i] = vectors[idx] total = 0 for i, dat in enumerate(data): total += dnp.abs((dat - targets[i]).length()) return total if not optimise_U: return U elif optimise_U: # The array gives a first estimate for the arguments for the diff # function. U_axis_angle = scm.r3_rotation_axis_and_angle_from_matrix(U) axis = Vector(U_axis_angle.axis) array = dnp.array([axis[0], axis[1], axis[2], U_axis_angle.angle()]) import scipy.optimize optimise = scipy.optimize.minimize(diff, array, (found_vectors_copy, all_vectors), bounds=[(-1, 1), (-1, 1), (-1, 1), (-dnp.pi, dnp.pi)]) if optimise['success']: new_axis = Vector((optimise.x[0], optimise.x[1], optimise.x[2])) new_U = Rotator(scm.r3_rotation_axis_and_angle_as_matrix(new_axis, optimise.x[3])) return new_U else: print optimise print diff(array, found_vectors_copy, all_vectors) new_axis = Vector((optimise.x[0], optimise.x[1], optimise.x[2])) new_U = Rotator(scm.r3_rotation_axis_and_angle_as_matrix(new_axis, optimise.x[3])) new_U_axis_angle = scm.r3_rotation_axis_and_angle_from_matrix( new_U) array = dnp.array([new_axis[0], new_axis[1], new_axis[2], new_U_axis_angle.angle()]) print 'U matrix optimisation failed.' return U else: raise Exception("""optimise_U must be a boolean type""")
def run(args): import libtbx.load_env from scitbx import matrix from cctbx.sgtbx import lattice_symmetry_group from scitbx.math import r3_rotation_axis_and_angle_from_matrix usage = "%s [options] experiment_0.json ..." % \ libtbx.env.dispatcher_name parser = OptionParser( usage=usage, phil=phil_scope, read_experiments=True, check_format=False, epilog=help_message) params, options = parser.parse_args(show_diff_phil=True) experiments = params.input.experiments # check input space_group = None for experiment in experiments: assert(len(experiment.data.goniometers()) == 1) assert(len(experiment.data.crystals()) == 1) crystal = experiment.data.crystals()[0] if space_group is None: space_group = crystal.get_space_group() else: assert(crystal.get_space_group() == space_group) reference_U = None reference_space_group = None for j, experiment in enumerate(experiments): goniometer = experiment.data.goniometers()[0] F = matrix.sqr(goniometer.get_fixed_rotation()) crystal = experiment.data.crystals()[0] U = matrix.sqr(crystal.get_U()) B = matrix.sqr(crystal.get_B()) UB = F * U * B UBt = UB.transpose().elems a, b, c = matrix.col(UBt[0:3]), matrix.col(UBt[3:6]), matrix.col(UBt[6:9]) axis = matrix.col(goniometer.get_rotation_axis()) from math import pi r2d = 180 / pi abc = [a, b, c] abc_names = 'abc' distances = [(r2d * (min(axis.angle(_a), pi - axis.angle(_a))), k) for k, _a in enumerate(abc)] close = sorted(distances)[0] if reference_U is None: reference_U = U reference_space_group = lattice_symmetry_group(crystal.get_unit_cell(), max_delta=0.0) print '%s possible lattice ops' % len(reference_space_group.all_ops()) print 'Experiment %d' % j print 'Closest (original) axis: %s* %.2f' % \ (abc_names[close[1]], close[0]) results = [] for op in reference_space_group.all_ops(): R = B * matrix.sqr(op.r().as_double()).transpose() * B.inverse() relative = (U * R).inverse() * reference_U rot = r3_rotation_axis_and_angle_from_matrix(relative) results.append((abs(rot.angle()), op.r().as_hkl(), rot)) results.sort() print 'Best reindex op for experiment %d: %12s (%.3f)' % \ (j, results[0][1], 180.0 * results[0][2].angle() / pi) if results[0][0] > (5 * pi / 180.0): print 'Rotation: axis: %.4f %.4f %.4f' % results[0][2].axis print ' angle: %.4f degrees' % \ (180.0 * results[0][2].angle() / pi)
def run(args): import libtbx.load_env from scitbx import matrix from cctbx.sgtbx import lattice_symmetry_group from scitbx.math import r3_rotation_axis_and_angle_from_matrix usage = "%s [options] experiment_0.expt ..." % libtbx.env.dispatcher_name parser = OptionParser( usage=usage, phil=phil_scope, read_experiments=True, check_format=False, epilog=help_message, ) params, options = parser.parse_args(show_diff_phil=True) experiments = params.input.experiments # check input space_group = None for experiment in experiments: assert len(experiment.data.goniometers()) == 1 assert len(experiment.data.crystals()) == 1 crystal = experiment.data.crystals()[0] if space_group is None: space_group = crystal.get_space_group() else: assert crystal.get_space_group() == space_group reference_U = None reference_space_group = None for j, experiment in enumerate(experiments): goniometer = experiment.data.goniometers()[0] F = matrix.sqr(goniometer.get_fixed_rotation()) crystal = experiment.data.crystals()[0] U = matrix.sqr(crystal.get_U()) B = matrix.sqr(crystal.get_B()) UB = F * U * B UBt = UB.transpose().elems a, b, c = matrix.col(UBt[0:3]), matrix.col(UBt[3:6]), matrix.col( UBt[6:9]) axis = matrix.col(goniometer.get_rotation_axis()) from math import pi r2d = 180 / pi abc = [a, b, c] abc_names = "abc" distances = [(r2d * (min(axis.angle(_a), pi - axis.angle(_a))), k) for k, _a in enumerate(abc)] close = sorted(distances)[0] if reference_U is None: reference_U = U reference_space_group = lattice_symmetry_group( crystal.get_unit_cell(), max_delta=0.0) print("%s possible lattice ops" % len(reference_space_group.all_ops())) print("Experiment %d" % j) print("Closest (original) axis: %s* %.2f" % (abc_names[close[1]], close[0])) results = [] for op in reference_space_group.all_ops(): R = B * matrix.sqr(op.r().as_double()).transpose() * B.inverse() relative = (U * R).inverse() * reference_U rot = r3_rotation_axis_and_angle_from_matrix(relative) results.append((abs(rot.angle()), op.r().as_hkl(), rot)) results.sort() print("Best reindex op for experiment %d: %12s (%.3f)" % (j, results[0][1], 180.0 * results[0][2].angle() / pi)) if results[0][0] > (5 * pi / 180.0): print("Rotation: axis: %.4f %.4f %.4f" % results[0][2].axis) print(" angle: %.4f degrees" % (180.0 * results[0][2].angle() / pi))
def find_U_matrix(found_vectors, crystal, beam_energy=8, optimise_U=True): """Given a Crystal class object with a cif file loaded into it, this function returns the U matrix as a dnp array. Args: found_vectors: A list of Vector class objects representing the momentum transfer vectors of the measured Bragg peaks. crystal: A Crystal class object. beam_energy: The beam energy in keV. optimise_U: If True the function optimises the U matrix before returning can be set to False if in Jython because requires scipy. Returns: U: The U matrix as a dnp object. """ # First gets all the allowed momentum transfer vectors of the crystal. grouped_reflections = f.group_reflections(crystal, beam_energy) all_vectors = [] for group in grouped_reflections: group_vectors = f.momentum_transfer_vectors(group, crystal) all_vectors += group_vectors # Find the target vectors. target_vectors = finding_the_targets(found_vectors, all_vectors) found_vectors_copy = copy.deepcopy(found_vectors) U = Rotator((1,0,0,0,1,0,0,0,1)) print U # Optimising the U matrix def diff(array, data, vectors): """This is a function used to optimise the U matrix. It evaluates """ x = array[0] y = array[1] z = array[2] # z = 1.0 angle = array[3] axis = Vector([x, y, z]) U = Rotator(scm.r3_rotation_axis_and_angle_as_matrix(axis, angle)) data = rotate_list(U, data) index_list=[] for i, dat in enumerate(data): diffs = [] dat = dat for j, vector in enumerate(vectors): diffs.append((dat-vector).length()) index = diffs.index(min(dnp.abs(diffs))) index_list.append(index) targets = [0]*len(data) for i, idx in enumerate(index_list): targets[i] = vectors[idx] total = 0 for i, dat in enumerate(data): total += (dat - targets[i]).length() return total*1000 if not optimise_U: return U elif optimise_U: U_axis_angle = scm.r3_rotation_axis_and_angle_from_matrix(U) axis = Vector(U_axis_angle.axis) # The array gives a first estimate for the arguments for the diff # function. array = dnp.array([axis[0], axis[1], axis[2], U_axis_angle.angle()]) print 'old diff', diff(array, found_vectors_copy, all_vectors) import scipy.optimize optimise = scipy.optimize.basinhopping(diff, array, minimizer_kwargs={'args':(found_vectors_copy, all_vectors)}) print optimise new_axis = Vector((optimise.x[0], optimise.x[1], optimise.x[2])) new_U = Rotator(scm.r3_rotation_axis_and_angle_as_matrix(new_axis.normalize(), optimise.x[3])) new_U_axis_angle = scm.r3_rotation_axis_and_angle_from_matrix( new_U) print 'new diff', diff(optimise, found_vectors_copy, all_vectors) print 'old ax', axis print 'new ax',new_axis return new_U else: raise Exception("""optimise_U must be a boolean type""")