def test_constructor_with_impossible_val(self): good_input = 1 good_center_input = [1, 2, 3] zero_value = 0 negative_value = -0.0000001 negative_int = -1 negative_string = "-1" # Check it handles zero with assertRaisesRegex(self, ValueError, "The value set for height was: 0"): sample_details.SampleDetails(height=zero_value, radius=good_input, center=good_center_input) # Very small negative with assertRaisesRegex(self, ValueError, "which is impossible for a physical object"): sample_details.SampleDetails(height=good_input, radius=negative_value, center=good_center_input) # Integer negative with assertRaisesRegex(self, ValueError, "The value set for height was: -1"): sample_details.SampleDetails(height=negative_int, radius=good_input, center=good_center_input) # String negative with assertRaisesRegex(self, ValueError, "The value set for radius was: -1"): sample_details.SampleDetails(height=good_input, radius=negative_string, center=good_center_input)
def test_generate_geometry_cylinder_with_container(self): workspace = CreateSampleWorkspace() # float radius_float = 1.0 height_float = 2.0 center_float = [1.0, 2.0, 3.0] sample_details_float = sample_details.SampleDetails( radius=radius_float, shape="cylinder", height=height_float, center=center_float) sample_details_float.set_material(chemical_formula='Si') sample_details_float.set_container(radius=2.0, chemical_formula='V') # int radius_int = 1 height_int = 3 center_int = [1, 2, 3] sample_details_int = sample_details.SampleDetails(radius=radius_int, shape="cylinder", height=height_int, center=center_int) sample_details_int.set_material(chemical_formula='Si') sample_details_int.set_container(radius=2, chemical_formula='V') # string radius_string = "1" height_string = "2" center_string = ["1", "2", "3"] sample_details_string = sample_details.SampleDetails( radius=radius_string, shape="cylinder", height=height_string, center=center_string) sample_details_string.set_material(chemical_formula='Si') sample_details_string.set_container(radius="2", chemical_formula='V') # mix radius_mix = 1.23 height_mix = 2 center_mix = ["1", 2, 3.45] sample_details_mix = sample_details.SampleDetails(radius=radius_mix, shape="cylinder", height=height_mix, center=center_mix) sample_details_mix.set_material(chemical_formula='Si') sample_details_mix.set_container(radius="2", chemical_formula='V') sample_details_objects = [ sample_details_float, sample_details_int, sample_details_string, sample_details_mix ] for sample_details_object in sample_details_objects: SetSample( workspace, Geometry=sample_details_object.generate_sample_geometry(), Material=sample_details_object.generate_sample_material(), ContainerGeometry=sample_details_object. generate_container_geometry(), ContainerMaterial=sample_details_object. generate_container_material())
def test_constructor(self): expected_height = 1.1 expected_radius = 2.2 expected_center = [3.3, 4.4, 5.5] # Check easiest case sample_details_obj = sample_details.SampleDetails( height=expected_height, radius=expected_radius, center=expected_center) self.assertEqual(sample_details_obj.height(), expected_height) self.assertEqual(sample_details_obj.radius(), expected_radius) self.assertEqual(sample_details_obj.center(), expected_center) # Check shape stype defaults to cylinder self.assertEqual(sample_details_obj.shape_type(), "cylinder") # Does it handle ints correctly height_radius_int = 1 center_int = [2, 3, 4] sample_details_obj_int = sample_details.SampleDetails( height=height_radius_int, radius=height_radius_int, center=center_int, shape="cylinder") self.assertTrue(isinstance(sample_details_obj.height(), float)) self.assertTrue(isinstance(sample_details_obj.radius(), float)) self.assertEqual(sample_details_obj_int.height(), float(height_radius_int)) self.assertEqual(sample_details_obj_int.radius(), float(height_radius_int)) self.assertEqual(sample_details_obj_int.center(), [2.0, 3.0, 4.0]) # Does it handle strings correctly height_radius_string = "5" center_string = ["2.0", "3.0", "5.0"] sample_details_obj_str = sample_details.SampleDetails( height=height_radius_string, radius=height_radius_string, center=center_string, shape="cylinder") self.assertTrue(isinstance(sample_details_obj.height(), float)) self.assertTrue(isinstance(sample_details_obj.radius(), float)) self.assertEqual(sample_details_obj_str.height(), float(height_radius_string)) self.assertEqual(sample_details_obj_str.radius(), float(height_radius_string)) self.assertEqual(sample_details_obj_str.center(), [2.0, 3.0, 5.0])
def test_constructor_non_number_input(self): good_input = 1.0 good_center_input = [1.0, 2.0, 3.0] empty_input_value = '' char_input_value = 'a' # Check it handles empty input with assertRaisesRegex(self, ValueError, "Could not convert the height to a number"): sample_details.SampleDetails(height=empty_input_value, radius=good_input, center=good_center_input) # Does it handle bad input and tell us what we put in with assertRaisesRegex( self, ValueError, ".*to a number. The input was: '" + char_input_value + "'"): sample_details.SampleDetails(height=char_input_value, radius=good_input, center=good_center_input) # Does it indicate which field was incorrect with assertRaisesRegex(self, ValueError, "radius"): sample_details.SampleDetails(height=good_input, radius=char_input_value, center=good_center_input) # Can it handle bad center values with assertRaisesRegex(self, ValueError, "center"): sample_details.SampleDetails(height=good_input, radius=good_input, center=["", 2, 3]) # Does it throw if were not using a list for the input with assertRaisesRegex(self, ValueError, "must be specified as a list of X, Y, Z"): sample_details.SampleDetails(height=good_input, radius=good_input, center=1) # Does it throw if we are using a list of incorrect length (e.g. not 3D) with assertRaisesRegex(self, ValueError, "must have three values corresponding to"): sample_details.SampleDetails(height=good_input, radius=good_input, center=[]) with assertRaisesRegex(self, ValueError, "must have three values corresponding to"): sample_details.SampleDetails(height=good_input, radius=good_input, center=[1, 2]) with assertRaisesRegex(self, ValueError, "must have three values corresponding to"): sample_details.SampleDetails(height=good_input, radius=good_input, center=[1, 2, 3, 4])
def test_generate_sample_geometry(self): # Create mock SampleDetails sample_details_obj = sample_details.SampleDetails( height=4.0, radius=3.0, center=[0.5, 1.0, -3.2], shape='cylinder') # Run test result = sample_details_obj.generate_sample_geometry() # Validate result expected = { 'Shape': 'Cylinder', 'Height': 4.0, 'Radius': 3.0, 'Center': [0.5, 1.0, -3.2] } self.assertEqual(result, expected)
def test_set_material_properties(self): sample_details_obj = sample_details.SampleDetails(height=1.0, radius=1.0, center=[2, 3, 5]) self.assertIsNone(sample_details_obj.material_object) # Check we cannot set a material property without setting the underlying material with assertRaisesRegex(self, RuntimeError, "The material has not been set"): sample_details_obj.set_material_properties( absorption_cross_section=1.0, scattering_cross_section=2.0) # Check that with a material object we are allowed to set material properties sample_details_obj.set_material(chemical_formula='V') # We will test the immutability of the underlying object elsewhere sample_details_obj.set_material_properties( scattering_cross_section=2.0, absorption_cross_section=3.0)
def test_generate_sample_material(self): # Create mock SampleDetails sample_details_obj = sample_details.SampleDetails( height=1.0, radius=1.0, center=[0.0, 0.0, 0.0]) sample_details_obj.set_material(chemical_formula='Si', number_density=1.5) sample_details_obj.set_material_properties( absorption_cross_section=123, scattering_cross_section=456) # Run test result = sample_details_obj.generate_sample_material() # Validate expected = { 'ChemicalFormula': 'Si', 'NumberDensity': 1.5, 'AttenuationXSection': 123.0, 'ScatteringXSection': 456.0 } self.assertEqual(result, expected)
def test_set_material(self): sample_details_obj = sample_details.SampleDetails(height=1.0, radius=1.0, center=[2, 3, 4]) # Check that we can only set a material once. We will test the underlying class elsewhere sample_details_obj.set_material(chemical_formula='V') self.assertIsNotNone(sample_details_obj.material_object) # Check that the material is now immutable with assertRaisesRegex( self, RuntimeError, "The material has already been set to the above details"): sample_details_obj.set_material(chemical_formula='V') # Check resetting it works sample_details_obj.reset_sample_material() self.assertIsNone(sample_details_obj.material_object) # And ensure setting it for a second time works sample_details_obj.set_material(chemical_formula='V') self.assertIsNotNone(sample_details_obj.material_object)
def create_vanadium_sample_details_obj(config_dict): """ Creates a SampleDetails object based on a vanadium sample which is found in the advanced config of an instrument. :param config_dict: The advanced config dictionary of the instrument for the vanadium sample :return: A sample details object which holds properties used in sample corrections """ height_key = "cylinder_sample_height" radius_key = "cylinder_sample_radius" pos_key = "cylinder_position" formula_key = "chemical_formula" number_density_key = "number_density" e_msg = "The following key was not found in the advanced configuration for sample correction:\n" height = common.dictionary_key_helper(dictionary=config_dict, key=height_key, exception_msg=e_msg + height_key) radius = common.dictionary_key_helper(dictionary=config_dict, key=radius_key, exception_msg=e_msg + radius_key) pos = common.dictionary_key_helper(dictionary=config_dict, key=pos_key, exception_msg=e_msg + pos_key) formula = common.dictionary_key_helper(dictionary=config_dict, key=formula_key, exception_msg=e_msg + formula_key) number_density = common.dictionary_key_helper(dictionary=config_dict, key=number_density_key, throws=False) vanadium_sample_details = sample_details.SampleDetails(height=height, radius=radius, center=pos, shape="cylinder") vanadium_sample_details.set_material(chemical_formula=formula, number_density=number_density) return vanadium_sample_details
def test_construct_slab(self): expected_thickness = 2.2 expected_width = 1.0 expected_height = 2.0 expected_center = [1.0, 2.0, 3.0] expected_angle = 3.0 # Check easiest case sample_details_obj = sample_details.SampleDetails( thickness=expected_thickness, shape="slab", height=expected_height, width=expected_width, center=expected_center, angle=expected_angle) self.assertEqual(sample_details_obj.thickness(), expected_thickness) self.assertEqual(sample_details_obj.width(), expected_width) self.assertEqual(sample_details_obj.height(), expected_height) self.assertEqual(sample_details_obj.center(), expected_center) self.assertEqual(sample_details_obj.angle(), expected_angle) # Does it handle ints correctly thickness_int = 1 width_int = 2 height_int = 3 center_int = [1, 2, 3] angle_int = 4 sample_details_obj_int = sample_details.SampleDetails( thickness=thickness_int, shape="slab", height=height_int, width=width_int, center=center_int, angle=angle_int) self.assertTrue(isinstance(sample_details_obj_int.thickness(), float)) self.assertTrue(isinstance(sample_details_obj_int.width(), float)) self.assertTrue(isinstance(sample_details_obj_int.height(), float)) self.assertTrue(isinstance(sample_details_obj_int.center(), list)) self.assertTrue( all(isinstance(p, float) for p in sample_details_obj_int.center())) self.assertTrue(isinstance(sample_details_obj_int.angle(), float)) self.assertEqual(sample_details_obj_int.thickness(), float(thickness_int)) self.assertEqual(sample_details_obj_int.width(), float(width_int)) self.assertEqual(sample_details_obj_int.height(), float(height_int)) self.assertEqual(sample_details_obj_int.center(), [float(p) for p in center_int]) self.assertEqual(sample_details_obj_int.angle(), float(angle_int)) # Does it handle strings correctly thickness_string = "5" width_string = "1" height_string = "2" center_string = ["1", "2", "3"] angle_string = "3" sample_details_obj_str = sample_details.SampleDetails( thickness=thickness_string, shape="slab", height=height_string, width=width_string, center=center_string, angle=angle_string) self.assertTrue(isinstance(sample_details_obj_str.thickness(), float)) self.assertTrue(isinstance(sample_details_obj_str.width(), float)) self.assertTrue(isinstance(sample_details_obj_str.height(), float)) self.assertTrue(isinstance(sample_details_obj_str.center(), list)) self.assertTrue( all(isinstance(p, float) for p in sample_details_obj_str.center())) self.assertTrue(isinstance(sample_details_obj_str.angle(), float)) self.assertEqual(sample_details_obj_str.thickness(), float(thickness_string)) self.assertEqual(sample_details_obj_str.width(), float(width_string)) self.assertEqual(sample_details_obj_str.height(), float(height_string)) self.assertEqual(sample_details_obj_str.center(), [float(p) for p in center_string]) self.assertEqual(sample_details_obj_str.angle(), float(angle_string))
def test_print_sample_details(self): expected_height = 1 expected_radius = 2 expected_center = [3, 4, 5] chemical_formula = 'Si' chemical_formula_two = 'V' expected_number_density = 1.2345 old_std_out = sys.stdout # Wrap in try finally so we always restore std out if any exception is thrown try: # Redirect std out to a capture object std_out_buffer = get_std_out_buffer_obj() sys.stdout = std_out_buffer sample_details_obj = sample_details.SampleDetails( height=expected_height, radius=expected_radius, center=expected_center, shape="cylinder") # Test with most defaults set sample_details_obj.print_sample_details() captured_std_out_default = std_out_buffer.getvalue() assertRegex(self, captured_std_out_default, "Height: " + str(float(expected_height))) assertRegex(self, captured_std_out_default, "Radius: " + str(float(expected_radius))) assertRegex(self, captured_std_out_default, "Center X:" + str(float(expected_center[0]))) assertRegex(self, captured_std_out_default, "Material has not been set") # Test with material set but not number density sys.stdout = std_out_buffer = get_std_out_buffer_obj() sample_details_obj.set_material(chemical_formula=chemical_formula) sample_details_obj.print_sample_details() captured_std_out_material_default = std_out_buffer.getvalue() assertRegex(self, captured_std_out_material_default, "Material properties:") assertRegex(self, captured_std_out_material_default, "Chemical formula: " + chemical_formula) assertRegex(self, captured_std_out_material_default, "Number Density: Set from elemental properties") # Test with material and number density sys.stdout = std_out_buffer = get_std_out_buffer_obj() sample_details_obj.reset_sample_material() sample_details_obj.set_material( chemical_formula=chemical_formula_two, number_density=expected_number_density) sample_details_obj.print_sample_details() captured_std_out_material_set = std_out_buffer.getvalue() assertRegex(self, captured_std_out_material_set, "Chemical formula: " + chemical_formula_two) assertRegex(self, captured_std_out_material_set, "Number Density: " + str(expected_number_density)) # Test with no material properties set - we can reuse buffer from previous test assertRegex(self, captured_std_out_material_default, "Absorption cross section: Calculated by Mantid") assertRegex(self, captured_std_out_material_default, "Scattering cross section: Calculated by Mantid") assertRegex(self, captured_std_out_material_default, "Note to manually override these call") expected_abs_x_section = 2.13 expected_scattering_x_section = 5.32 # Test with material set sys.stdout = std_out_buffer = get_std_out_buffer_obj() sample_details_obj.set_material_properties( absorption_cross_section=expected_abs_x_section, scattering_cross_section=expected_scattering_x_section) sample_details_obj.print_sample_details() captured_std_out_material_props = std_out_buffer.getvalue() assertRegex( self, captured_std_out_material_props, "Absorption cross section: " + str(expected_abs_x_section)) assertRegex( self, captured_std_out_material_props, "Scattering cross section: " + str(expected_scattering_x_section)) finally: # Ensure std IO is restored. Do NOT remove this line as all std out will pipe into our buffer otherwise sys.stdout = old_std_out
def test_generate_geometry_slab_with_container(self): workspace = CreateSampleWorkspace() thickness_float = 2.2 width_float = 1.0 height_float = 2.0 center_float = [1.0, 2.0, 3.0] angle_float = 3.0 sample_details_float = sample_details.SampleDetails( thickness=thickness_float, shape="slab", height=height_float, width=width_float, center=center_float, angle=angle_float) sample_details_float.set_material(chemical_formula='Si') sample_details_float.set_container(front_thick=2.0, back_thick=2.2, chemical_formula='V') thickness_int = 1 width_int = 2 height_int = 3 center_int = [1, 2, 3] angle_int = 4 sample_details_int = sample_details.SampleDetails( thickness=thickness_int, shape="slab", height=height_int, width=width_int, center=center_int, angle=angle_int) sample_details_int.set_material(chemical_formula='Si') sample_details_int.set_container(front_thick=2, back_thick=1, chemical_formula='V') thickness_string = "5" width_string = "1" height_string = "2" center_string = ["1", "2", "3"] angle_string = "3" sample_details_string = sample_details.SampleDetails( thickness=thickness_string, shape="slab", height=height_string, width=width_string, center=center_string, angle=angle_string) sample_details_string.set_material(chemical_formula='Si') sample_details_string.set_container(front_thick="2", back_thick="2.2", chemical_formula='V') thickness_mix = "5" width_mix = 3.5 height_mix = "2" center_mix = ["1", 2, 3.45] angle_mix = 3 sample_details_mix = sample_details.SampleDetails( thickness=thickness_mix, shape="slab", height=height_mix, width=width_mix, center=center_mix, angle=angle_mix) sample_details_mix.set_material(chemical_formula='Si') sample_details_mix.set_container(front_thick="2.0", back_thick=2, chemical_formula='V') sample_details_objects = [ sample_details_float, sample_details_int, sample_details_string, sample_details_mix ] for sample_details_object in sample_details_objects: SetSample( workspace, Geometry=sample_details_object.generate_sample_geometry(), Material=sample_details_object.generate_sample_material(), ContainerGeometry=sample_details_object. generate_container_geometry(), ContainerMaterial=sample_details_object. generate_container_material())