class TestSolutionGenerator(): def setup(self): names = ['delta', NUNAME, 'mu', 'eta', 'chi', 'phi'] self.hardware = SimpleHardwareAdapter(names) self.calc = YouHklCalculator(createMockUbcalc(None), createMockDiffractometerGeometry(), self.hardware, Mock()) # constraint could have been 'delta', NUNAME, 'qaz' or 'naz'. def test_generate_possible_det_soln_no_limits_constrained_qaz_or_naz(self): # we will enfoce the order too, incase this later effects heuristically # made choices expected = ( (.1, .2), (.1, -.2), (.1, .2 - pi), (.1, pi - .2), (-.1, .2), (-.1, -.2), (-.1, .2 - pi), (-.1, pi - .2), (.1 - pi, .2), # pi + x cuts to x-pi (.1 - pi, -.2), (.1 - pi, .2 - pi), (.1 - pi, pi - .2), (pi - .1, .2), (pi - .1, -.2), (pi - .1, .2 - pi), (pi - .1, pi - .2), ) assert_2darray_almost_equal(expected, self.calc._generate_possible_solutions( (.1, .2), ('delta', NUNAME), ('naz',))) assert_2darray_almost_equal(expected, self.calc._generate_possible_solutions( (.1, .2), ('delta', NUNAME), ('qaz',))) def test_generate_poss_det_soln_no_lim_cons_qaz_or_naz_delta_and_nu_at_zro(self): # @IgnorePep8 # we will enfoce the order too, incase this later effects hearistically # made choices expected = ( (0., 0,), (0., pi), (pi, 0.), (pi, pi) ) assert_2darray_almost_equal(expected, self.calc._generate_possible_solutions( (-2e-9, 2e-9), ('delta', NUNAME), ('naz',))) assert_2darray_almost_equal(expected, self.calc._generate_possible_solutions( (-2e-9, 2e-9), ('delta', NUNAME), ('qaz',))) def test_generate_possible_det_solutions_no_limits_constrained_delta(self): expected = ( (.1, .2), (.1, -.2), (.1, .2 - pi), (.1, pi - .2), ) assert_2darray_almost_equal(expected, self.calc._generate_possible_solutions( (.1, .2), ('delta', NUNAME), ('delta',))) def test_generate_possible_det_solutions_no_limits_constrained_nu(self): expected = ( (.1, .2), (-.1, .2), (.1 - pi, .2), (pi - .1, .2), ) assert_2darray_almost_equal(expected, self.calc._generate_possible_solutions( (.1, .2), ('delta', NUNAME), (NUNAME,))) def test_generate_possible_det_soln_with_limits_constrained_delta(self): self.hardware.set_lower_limit(NUNAME, 0) expected = ( (.1, .2), (.1, pi - .2), ) assert_2darray_almost_equal(expected, self.calc._generate_possible_solutions( (.1, .2), ('delta', NUNAME), ('delta',))) def test_generate_possible_det_solutions_with_limits_constrained_nu(self): self.hardware.set_upper_limit('delta', 0) expected = ( (-.1, .2), (.1 - pi, .2), # cuts to .1-pi ) assert_2darray_almost_equal(expected, self.calc._generate_possible_solutions( (.1, .2), ('delta', NUNAME), (NUNAME,))) def test_generate_poss_det_soln_with_limits_overly_constrained_nu(self): self.hardware.set_lower_limit('delta', .3) self.hardware.set_upper_limit('delta', .31) eq_(len(self.calc._generate_possible_solutions( (.1, .2), ('delta', NUNAME), (NUNAME,))), 0) def test_generate_possible_sample_solutions(self): result = self.calc._generate_possible_solutions( (.1, .2, .3, .4), ('mu', 'eta', 'chi', 'phi'), ('naz',)) generated = self._hardcoded_generate_possible_sample_solutions( .1, .2, .3, .4, 'naz') assert_2darray_almost_equal(generated, result) eq_(4 ** 4, len(result)) def test_generate_possible_sample_solutions_fixed_chi(self): result = self.calc._generate_possible_solutions( (.1, .2, .3, .4), ('mu', 'eta', 'chi', 'phi'), ('chi',)) generated = self._hardcoded_generate_possible_sample_solutions( .1, .2, .3, .4, 'chi') assert_2darray_almost_equal(generated, result) eq_(4 ** 3, len(result)) def test_generate_possible_sample_solutions_fixed_chi_positive_mu(self): self.hardware.set_lower_limit('mu', 0) result = self.calc._generate_possible_solutions( (.1, .2, .3, .4), ('mu', 'eta', 'chi', 'phi'), ('chi',)) generated = self._hardcoded_generate_possible_sample_solutions( .1, .2, .3, .4, 'chi') assert_2darray_almost_equal(generated, result) eq_(2 * (4 ** 2), len(result)) def _hardcoded_generate_possible_sample_solutions(self, mu, eta, chi, phi, sample_constraint_name): possible_solutions = [] _identity = lambda x: x _transforms = (_identity, lambda x: -x, lambda x: pi + x, lambda x: pi - x) _transforms_for_zero = (lambda x: 0., lambda x: pi,) SMALL = 1e-8 def cut_at_minus_pi(value): if value < (-pi - SMALL): return value + 2 * pi if value >= pi + SMALL: return value - 2 * pi return value def is_small(x): return abs(x) < SMALL name = sample_constraint_name for transform in ((_identity,) if name == 'mu' else _transforms if not is_small(mu) else _transforms_for_zero): transformed_mu = (transform(mu)) if not self.hardware.is_axis_value_within_limits('mu', self.hardware.cut_angle('mu', transformed_mu * TODEG)): continue for transform in ((_identity,) if name == 'eta' else _transforms if not is_small(eta) else _transforms_for_zero): transformed_eta = transform(eta) if not self.hardware.is_axis_value_within_limits('eta', self.hardware.cut_angle('eta', transformed_eta * TODEG)): continue for transform in ((_identity,) if name == 'chi' else _transforms if not is_small(chi) else _transforms_for_zero): transformed_chi = transform(chi) if not self.hardware.is_axis_value_within_limits('chi', self.hardware.cut_angle('chi', transformed_chi * TODEG)): continue for transform in ((_identity,) if name == 'phi' else _transforms if not is_small(phi) else _transforms_for_zero): transformed_phi = transform(phi) if not self.hardware.is_axis_value_within_limits('phi', self.hardware.cut_angle('phi', transformed_phi * TODEG)): continue possible_solutions.append(( cut_at_minus_pi(transformed_mu), cut_at_minus_pi(transformed_eta), cut_at_minus_pi(transformed_chi), cut_at_minus_pi(transformed_phi))) return possible_solutions
class TestSolutionGenerator(): def setup_method(self): names = ['delta', NUNAME, 'mu', 'eta', 'chi', 'phi'] self.hardware = SimpleHardwareAdapter(names) self.calc = YouHklCalculator(createMockUbcalc(None), createMockDiffractometerGeometry(), self.hardware, Mock()) # constraint could have been 'delta', NUNAME, 'qaz' or 'naz'. def test_generate_possible_det_soln_no_limits_constrained_qaz_or_naz(self): # we will enfoce the order too, incase this later effects heuristically # made choices expected = ( (.1, .2), (.1, -.2), (.1, .2 - pi), (.1, pi - .2), (-.1, .2), (-.1, -.2), (-.1, .2 - pi), (-.1, pi - .2), (.1 - pi, .2), # pi + x cuts to x-pi (.1 - pi, -.2), (.1 - pi, .2 - pi), (.1 - pi, pi - .2), (pi - .1, .2), (pi - .1, -.2), (pi - .1, .2 - pi), (pi - .1, pi - .2), ) assert_2darray_almost_equal( expected, self.calc._generate_possible_solutions((.1, .2), ('delta', NUNAME), ('naz', ))) assert_2darray_almost_equal( expected, self.calc._generate_possible_solutions((.1, .2), ('delta', NUNAME), ('qaz', ))) def test_generate_poss_det_soln_no_lim_cons_qaz_or_naz_delta_and_nu_at_zro( self): # @IgnorePep8 # we will enfoce the order too, incase this later effects hearistically # made choices expected = (( 0., 0, ), (0., pi), (pi, 0.), (pi, pi)) assert_2darray_almost_equal( expected, self.calc._generate_possible_solutions( (-2e-9, 2e-9), ('delta', NUNAME), ('naz', ))) assert_2darray_almost_equal( expected, self.calc._generate_possible_solutions( (-2e-9, 2e-9), ('delta', NUNAME), ('qaz', ))) def test_generate_possible_det_solutions_no_limits_constrained_delta(self): expected = ( (.1, .2), (.1, -.2), (.1, .2 - pi), (.1, pi - .2), ) assert_2darray_almost_equal( expected, self.calc._generate_possible_solutions((.1, .2), ('delta', NUNAME), ('delta', ))) def test_generate_possible_det_solutions_no_limits_constrained_nu(self): expected = ( (.1, .2), (-.1, .2), (.1 - pi, .2), (pi - .1, .2), ) assert_2darray_almost_equal( expected, self.calc._generate_possible_solutions((.1, .2), ('delta', NUNAME), (NUNAME, ))) def test_generate_possible_det_soln_with_limits_constrained_delta(self): self.hardware.set_lower_limit(NUNAME, 0) expected = ( (.1, .2), (.1, pi - .2), ) assert_2darray_almost_equal( expected, self.calc._generate_possible_solutions((.1, .2), ('delta', NUNAME), ('delta', ))) def test_generate_possible_det_solutions_with_limits_constrained_nu(self): self.hardware.set_upper_limit('delta', 0) expected = ( (-.1, .2), (.1 - pi, .2), # cuts to .1-pi ) assert_2darray_almost_equal( expected, self.calc._generate_possible_solutions((.1, .2), ('delta', NUNAME), (NUNAME, ))) def test_generate_poss_det_soln_with_limits_overly_constrained_nu(self): self.hardware.set_lower_limit('delta', .3) self.hardware.set_upper_limit('delta', .31) eq_( len( self.calc._generate_possible_solutions( (.1, .2), ('delta', NUNAME), (NUNAME, ))), 0) def test_generate_possible_sample_solutions(self): result = self.calc._generate_possible_solutions( (.1, .2, .3, .4), ('mu', 'eta', 'chi', 'phi'), ('naz', )) generated = self._hardcoded_generate_possible_sample_solutions( .1, .2, .3, .4, 'naz') assert_2darray_almost_equal(generated, result) eq_(4**4, len(result)) def test_generate_possible_sample_solutions_fixed_chi(self): result = self.calc._generate_possible_solutions( (.1, .2, .3, .4), ('mu', 'eta', 'chi', 'phi'), ('chi', )) generated = self._hardcoded_generate_possible_sample_solutions( .1, .2, .3, .4, 'chi') assert_2darray_almost_equal(generated, result) eq_(4**3, len(result)) def test_generate_possible_sample_solutions_fixed_chi_positive_mu(self): self.hardware.set_lower_limit('mu', 0) result = self.calc._generate_possible_solutions( (.1, .2, .3, .4), ('mu', 'eta', 'chi', 'phi'), ('chi', )) generated = self._hardcoded_generate_possible_sample_solutions( .1, .2, .3, .4, 'chi') assert_2darray_almost_equal(generated, result) eq_(2 * (4**2), len(result)) def _hardcoded_generate_possible_sample_solutions(self, mu, eta, chi, phi, sample_constraint_name): possible_solutions = [] _identity = lambda x: x _transforms = (_identity, lambda x: -x, lambda x: pi + x, lambda x: pi - x) _transforms_for_zero = ( lambda x: 0., lambda x: pi, ) SMALL = 1e-8 def cut_at_minus_pi(value): if value < (-pi - SMALL): return value + 2 * pi if value >= pi + SMALL: return value - 2 * pi return value def is_small(x): return abs(x) < SMALL name = sample_constraint_name for transform in ((_identity, ) if name == 'mu' else _transforms if not is_small(mu) else _transforms_for_zero): transformed_mu = (transform(mu)) if not self.hardware.is_axis_value_within_limits( 'mu', self.hardware.cut_angle('mu', transformed_mu * TODEG)): continue for transform in ((_identity, ) if name == 'eta' else _transforms if not is_small(eta) else _transforms_for_zero): transformed_eta = transform(eta) if not self.hardware.is_axis_value_within_limits( 'eta', self.hardware.cut_angle('eta', transformed_eta * TODEG)): continue for transform in ((_identity, ) if name == 'chi' else _transforms if not is_small(chi) else _transforms_for_zero): transformed_chi = transform(chi) if not self.hardware.is_axis_value_within_limits( 'chi', self.hardware.cut_angle('chi', transformed_chi * TODEG)): continue for transform in ((_identity, ) if name == 'phi' else _transforms if not is_small(phi) else _transforms_for_zero): transformed_phi = transform(phi) if not self.hardware.is_axis_value_within_limits( 'phi', self.hardware.cut_angle( 'phi', transformed_phi * TODEG)): continue possible_solutions.append( (cut_at_minus_pi(transformed_mu), cut_at_minus_pi(transformed_eta), cut_at_minus_pi(transformed_chi), cut_at_minus_pi(transformed_phi))) return possible_solutions