Ejemplo n.º 1
0
    def setUp(self):
        # blank/temporary HDF5 file
        self.f = FauxHDFBuilder()

        # fill the MSI group for testing
        self.f['MSI'].create_group('g1')
        self.f['MSI'].create_group('g2')

        # correct 'command list' dataset
        dtype = np.dtype([('Shot number', np.int32),
                          ('Command index', np.int8)])
        data = np.empty((5, ), dtype=dtype)
        self.f['MSI'].create_dataset('d1', data=data)

        # dataset missing 'Command index'
        dtype = np.dtype([('Shot number', np.int32),
                          ('Not command index', np.int8)])
        data = np.empty((5, ), dtype=dtype)
        self.f['MSI'].create_dataset('d2', data=data)

        # dataset missing 'Command index' wrong shape and size
        dtype = np.dtype([('Shot number', np.int32),
                          ('Command index', np.float16, (2, ))])
        data = np.empty((5, ), dtype=dtype)
        self.f['MSI'].create_dataset('d3', data=data)
Ejemplo n.º 2
0
    def setUpClass(cls):
        # skip tests if in MSIDiagnosticTestCase
        if cls is DigitizerTestCase:
            raise ut.SkipTest("In DigitizerTestCase, " "skipping base tests")
        super().setUpClass()

        # create HDF5 file
        cls.f = FauxHDFBuilder()
Ejemplo n.º 3
0
    def setUpClass(cls):
        # skip tests if in ControlTestCase
        if cls is ControlTestCase:
            raise ut.SkipTest("In ControlTestCase, skipping base tests")
        super().setUpClass()

        # create HDF5 file
        cls.f = FauxHDFBuilder()
Ejemplo n.º 4
0
    def setUp(self):
        # blank/temporary HDF5 file
        self.f = FauxHDFBuilder()

        # fill the MSI group for testing
        self.f["MSI"].create_group("g1")
        self.f["MSI"].create_group("g2")

        # correct 'command list' dataset
        dtype = np.dtype([("Shot number", np.int32), ("Command index", np.int8)])
        data = np.empty((5,), dtype=dtype)
        self.f["MSI"].create_dataset("d1", data=data)

        # dataset missing 'Command index'
        dtype = np.dtype([("Shot number", np.int32), ("Not command index", np.int8)])
        data = np.empty((5,), dtype=dtype)
        self.f["MSI"].create_dataset("d2", data=data)

        # dataset missing 'Command index' wrong shape and size
        dtype = np.dtype([("Shot number", np.int32), ("Command index", np.float16, (2,))])
        data = np.empty((5,), dtype=dtype)
        self.f["MSI"].create_dataset("d3", data=data)
Ejemplo n.º 5
0
 def setUpClass(cls) -> None:
     # create HDF5 file
     super().setUpClass()
     cls.f = FauxHDFBuilder()
Ejemplo n.º 6
0
class TestControlTemplates(ut.TestCase):
    """
    Test class for HDFMapControlTemplate and
    HDFMapControlCLTemplate.
    """
    def setUp(self):
        # blank/temporary HDF5 file
        self.f = FauxHDFBuilder()

        # fill the MSI group for testing
        self.f['MSI'].create_group('g1')
        self.f['MSI'].create_group('g2')

        # correct 'command list' dataset
        dtype = np.dtype([('Shot number', np.int32),
                          ('Command index', np.int8)])
        data = np.empty((5, ), dtype=dtype)
        self.f['MSI'].create_dataset('d1', data=data)

        # dataset missing 'Command index'
        dtype = np.dtype([('Shot number', np.int32),
                          ('Not command index', np.int8)])
        data = np.empty((5, ), dtype=dtype)
        self.f['MSI'].create_dataset('d2', data=data)

        # dataset missing 'Command index' wrong shape and size
        dtype = np.dtype([('Shot number', np.int32),
                          ('Command index', np.float16, (2, ))])
        data = np.empty((5, ), dtype=dtype)
        self.f['MSI'].create_dataset('d3', data=data)

    def tearDown(self):
        """Cleanup temporary HDF5 file"""
        self.f.cleanup()

    def group(self):
        """HDF5 group for testing"""
        return self.f['MSI']

    @staticmethod
    def dummy_map(template, group):
        """A template mapping of a HDF5 group"""
        # Note: Since the template classes contain abstract methods that
        #       are intended to be overwritten, those methods must be
        #       overwritten before instantiating an object.
        #
        # retrieve desired template class
        template_cls = DummyTemplates[template].value

        # override abstract methods
        # - all abstract methods will now return NotImplemented instead
        #   of raising NotImplementedError
        #
        new_dict = template_cls.__dict__.copy()
        for abstractmethod in template_cls.__abstractmethods__:
            new_dict[abstractmethod] = lambda *args: NotImplemented

        # define new template class
        new_template_class = type("dummy_%s" % template_cls.__name__,
                                  (template_cls, ), new_dict)

        # return map
        return new_template_class(group)

    def test_not_h5py_group(self):
        """Test error if object to map is not h5py.Group"""
        with self.assertRaises(TypeError):
            self.dummy_map('default', None)
            self.dummy_map('cl', None)

    def test_structure(self):
        # test HDFMapControlTemplate
        self.assertControlTemplate(self.dummy_map('default', self.group()),
                                   self.group())

        # test HDFMapControlCLTemplate
        self.assertControlCLTemplate(self.dummy_map('cl', self.group()),
                                     self.group())

    def assertControlTemplate(self, _map, _group: h5py.Group):
        # check instance
        self.assertIsInstance(_map, HDFMapControlTemplate)

        # check attribute existence
        attrs = ('info', 'configs', 'contype', 'dataset_names', 'group',
                 'has_command_list', 'one_config_per_dset', 'subgroup_names',
                 'device_name', 'construct_dataset_name', '_build_configs')
        for attr in attrs:
            self.assertTrue(hasattr(_map, attr))

        # -- check 'info'                                           ----
        # assert is a dict
        self.assertIsInstance(_map.info, dict)

        # assert required keys
        self.assertIn('group name', _map.info)
        self.assertIn('group path', _map.info)
        self.assertIn('contype', _map.info)

        # assert values
        self.assertEqual(_map.info['group name'],
                         os.path.basename(_group.name))
        self.assertEqual(_map.info['group path'], _group.name)
        self.assertEqual(_map.info['contype'], NotImplemented)

        # -- check 'configs'                                        ----
        self.assertIsInstance(_map.configs, dict)
        self.assertEqual(len(_map.configs), 0)

        # -- check 'one_config_per_dset'                            ----
        # empty configs dict
        self.assertFalse(_map.one_config_per_dset)

        # one config for three datasets
        with mock.patch.dict(_map._configs, {'config1': {}}):
            self.assertFalse(_map.one_config_per_dset)

        # 3 configs for 3 datasets
        with mock.patch.dict(_map._configs, {
                'config1': {},
                'config2': {},
                'config3': {}
        }):
            self.assertTrue(_map.one_config_per_dset)

        # -- check 'has_command_list'                               ----
        # empty configs dict
        self.assertFalse(_map.has_command_list)

        # add artificial 'command list'
        with mock.patch.dict(_map.configs, {
                'config1': {},
                'config2': {
                    'command list': ('start', )
                }
        }):
            self.assertTrue(_map.has_command_list)

        # -- check other attributes                                 ----
        self.assertEqual(_map.contype, _map.info['contype'])
        self.assertEqual(_map.group, _group)
        self.assertEqual(_map.device_name, _map.info['group name'])
        self.assertEqual(sorted(_map.dataset_names), sorted(['d1', 'd2',
                                                             'd3']))
        self.assertEqual(sorted(_map.subgroup_names), sorted(['g1', 'g2']))

        # -- check abstract methods                                 ----
        # Note: `self.dummy_map` overrides all abstract methods to
        #       return NotImplemented values
        #
        self.assertEqual(_map.construct_dataset_name(), NotImplemented)
        self.assertEqual(_map._build_configs(), NotImplemented)

    def assertControlCLTemplate(self, _map, _group: h5py.Group):
        # check instance
        self.assertIsInstance(_map, HDFMapControlCLTemplate)

        # re-assert HDFMapControlTemplate structure
        self.assertControlTemplate(_map, _group)

        # check attribute existence
        attrs = (
            '_default_re_patterns',
            'clparse',
            '_construct_state_values_dict',
            'reset_state_values_config',
            'set_state_values_config',
            '_default_state_values_dict',
        )
        for attr in attrs:
            self.assertTrue(hasattr(_map, attr))

        # -- check '_default_re_patterns'                           ----
        self.assertIsInstance(_map._default_re_patterns, tuple)
        self.assertEqual(len(_map._default_re_patterns), 0)

        # -- check 'clparse'                                        ----
        with mock.patch.dict(_map._configs,
                             {'config1': {
                                 'command list': ('VOLT 25.0', )
                             }}):
            self.assertIsInstance(_map.clparse('config1'), CLParse)

        # -- check '_construct_state_values_dict'                   ----
        cl = (
            'VOLT 20.0',
            'VOLT 25.0',
            'VOLT 30.0',
        )
        config_name = 'config1'
        configs_dict = {
            config_name: {
                'command list': cl,
                'dset paths': ('/MSI/d1', )
            }
        }
        clparse_dict = {
            'VOLT': {
                'command list': (20.0, 25.0, 30.0),
                'cl str': cl,
                'dtype': np.float64
            }
        }
        pattern = \
            r'(?P<VOLT>(\bVOLT\s)(?P<VAL>(\d+\.\d*|\.\d+|\d+\b)))'

        # run tests on a mock _map._configs
        with mock.patch.dict(_map._configs, configs_dict):
            # mock CLParse attribute 'apply_patterns'
            with mock.patch.object(CLParse, 'apply_patterns', ) as \
                    mock_apply_pat:
                # 'apply_patterns' is unsuccessful
                mock_apply_pat.return_value = (False, {})
                sv_dict = _map._construct_state_values_dict(
                    config_name, [pattern])
                self.assertFalse(bool(sv_dict))

                # 'apply_patterns' is successful
                mock_apply_pat.return_value = (True, clparse_dict)
                sv_dict = _map._construct_state_values_dict(
                    config_name, [pattern])
                self.assertTrue(bool(sv_dict))
                self.assertIsInstance(sv_dict, dict)
                self.assertEqual(len(sv_dict), 1)
                self.assertEqual(sv_dict['VOLT']['dset paths'],
                                 configs_dict[config_name]['dset paths'])
                self.assertEqual(sv_dict['VOLT']['dset field'],
                                 ('Command index', ))
                self.assertEqual(sv_dict['VOLT']['shape'], ())
                self.assertEqual(sv_dict['VOLT']['dtype'],
                                 clparse_dict['VOLT']['dtype'])
                self.assertEqual(sv_dict['VOLT']['command list'],
                                 clparse_dict['VOLT']['command list'])
                self.assertEqual(sv_dict['VOLT']['cl str'],
                                 clparse_dict['VOLT']['cl str'])

                # the 'dset_paths' dataset does NOT have 'Command index'
                configs_dict[config_name]['dset paths'] = ('/MSI/d2', )
                with self.assertWarns(UserWarning):
                    sv_dict = _map._construct_state_values_dict(
                        config_name, [pattern])
                    self.assertFalse(bool(sv_dict))

                # the 'dset_paths' dataset 'Command index' field does
                # NOT have correct shape or dtype
                configs_dict[config_name]['dset paths'] = ('/MSI/d3', )
                with self.assertWarns(UserWarning):
                    sv_dict = _map._construct_state_values_dict(
                        config_name, [pattern])
                    self.assertFalse(bool(sv_dict))

        # -- check 'reset_state_values_config'                      ----
        cl = ('VOLT 20.0', 'VOLT 25.0', 'VOLT 30.0')
        pattern = \
            r'(?P<VOLT>(\bVOLT\s)(?P<VAL>(\d+\.\d*|\.\d+|\d+\b)))'
        config_name = 'config1'
        configs_dict = {
            config_name: {
                'command list': cl,
                'dset paths': ('/MSI/d1', ),
                'shotnum': {},
                'state values': {}
            }
        }
        dsv_dict = {
            'command': {
                'command list': cl,
                'cl str': cl,
                're pattern': None,
                'dset paths': configs_dict[config_name]['dset paths'],
                'dset field': ('Command index', ),
                'shape': (),
                'dtype': np.dtype((np.unicode_, 10))
            }
        }
        sv_dict = {
            'VOLT': {
                'command list': (20.0, 25.0, 30.0),
                'cl str': cl,
                're pattern': re.compile(pattern),
                'dset paths': configs_dict[config_name]['dset paths'],
                'dset field': ('Command index', ),
                'shape': (),
                'dtype': np.float64
            }
        }

        # mock _map._configs
        # mock the '_default_state_values_dict' method
        with mock.patch.dict(_map._configs, configs_dict), \
             mock.patch.object(_map, '_default_state_values_dict') \
                as mock_dsvdict:
            mock_dsvdict.return_value = dsv_dict

            # kwarg apply_patterns=False (default behavior)
            _map.reset_state_values_config(config_name, apply_patterns=False)
            self.assertEqual(_map._configs[config_name]['state values'],
                             dsv_dict)

            # kwarg apply_patterns=True
            # mock '_construct_state_values_dict'
            with mock.patch.object(
                    _map, '_construct_state_values_dict') as mock_csvd:
                # '_construct_state_values_dict' returns {}
                mock_csvd.return_value = {}
                _map._configs[config_name]['state values'] = {}
                _map.reset_state_values_config(config_name,
                                               apply_patterns=True)
                self.assertEqual(_map._configs[config_name]['state values'],
                                 dsv_dict)

                # '_construct_state_values_dict' returns sv_dict
                mock_csvd.return_value = sv_dict
                _map._configs[config_name]['state values'] = {}
                _map.reset_state_values_config(config_name,
                                               apply_patterns=True)
                self.assertEqual(_map._configs[config_name]['state values'],
                                 sv_dict)

        # -- check 'set_state_values_config'                        ----
        cl = ('VOLT 20.0', 'VOLT 25.0', 'VOLT 30.0')
        pattern = \
            r'(?P<VOLT>(\bVOLT\s)(?P<VAL>(\d+\.\d*|\.\d+|\d+\b)))'
        config_name = 'config1'
        configs_dict = {
            config_name: {
                'command list': cl,
                'dset paths': ('/MSI/d1', ),
                'shotnum': {},
                'state values': {}
            }
        }
        sv_dict = {
            'VOLT': {
                'command list': (20.0, 25.0, 30.0),
                'cl str': cl,
                're pattern': re.compile(pattern),
                'dset paths': configs_dict[config_name]['dset paths'],
                'dset field': ('Command index', ),
                'shape': (),
                'dtype': np.float64
            }
        }

        # mock _map._configs
        # mock the '_construct_state_values_dict' method
        with mock.patch.dict(_map._configs, configs_dict), \
             mock.patch.object(_map, '_construct_state_values_dict') \
                as mock_csvd:
            # '_construct_state_values_dict' fails and returns {}
            mock_csvd.return_value = {}
            with self.assertWarns(UserWarning):
                _map.set_state_values_config(config_name, [pattern])
                self.assertEqual(_map._configs[config_name]['state values'],
                                 {})

            # '_construct_state_values_dict' fails and returns sv_dict
            mock_csvd.return_value = sv_dict
            _map._configs[config_name]['state values'] = {}
            _map.set_state_values_config(config_name, [pattern])
            self.assertEqual(_map._configs[config_name]['state values'],
                             sv_dict)

        # -- check abstract methods                                 ----
        # Note: `self.dummy_map` overrides all abstract methods to
        #       return NotImplemented values
        #
        self.assertEqual(_map._default_state_values_dict(''), NotImplemented)
Ejemplo n.º 7
0
 def setUpClass(cls):
     # create HDF5 file
     super().setUpClass()
     cls.f = FauxHDFBuilder()
     cls.f.create_group(cls.DEVICE_PATH)
Ejemplo n.º 8
0
 def setUp(self):
     self.f = FauxHDFBuilder()
Ejemplo n.º 9
0
class TestHDFMapMSI(ut.TestCase):
    """Test class for HDFMapMSI"""

    # What to test?
    # X  1. returned object is a dictionary
    # X  2. if input is not h5py.Group instance, then TypeError is
    #       raised
    # X  3. existence of:
    #       a. mappable_devices
    #          - check it's a tuple
    # X  4. MSI group has no sub-groups
    #       - dict is empty
    # X  5. MSI has unknown & known sub-groups
    #       - only known group is added to dictionary
    # X  6. MSI has a known sub-group, but mapping fails
    #       - failed map should not be added to to dict
    # X  7. all diagnostics are mappable, but not all mappable
    #       diagnostics are included
    # X  8. MSI group has a diagnostic dataset
    #

    def setUp(self):
        self.f = FauxHDFBuilder()

    def tearDown(self):
        self.f.cleanup()

    @property
    def map(self):
        """Map of MSI Group"""
        return self.map_msi(self.msi_group)

    @property
    def msi_group(self):
        """MSI group"""
        return self.f['MSI']

    @staticmethod
    def map_msi(group):
        """Mapping function"""
        return HDFMapMSI(group)

    def test_not_h5py_group(self):
        """Test error if object to map is not h5py.Group"""
        with self.assertRaises(TypeError):
            self.map_msi(None)

    def test_msi_scenarios(self):
        """
        Test various scenarios of mappable and non-mappable diagnostics
        in the MSI group
        """
        # the MSI group is empty                                    ----
        self.f.remove_all_modules()
        _map = self.map
        self.assertBasics(_map)
        self.assertEqual(_map, {})

        # the MSI group has all mappable diagnostics                ----
        self.f.remove_all_modules()
        self.f.add_module('Discharge', {})
        self.f.add_module('Heater', {})
        self.f.add_module('Magnetic field', {})
        _map = self.map
        self.assertBasics(_map)

        # check all diagnostics were mapped
        self.assertEqual(len(_map), 3)
        self.assertIn('Discharge', _map)
        self.assertIn('Heater', _map)
        self.assertIn('Magnetic field', _map)

        # the MSI group has mappable and unknown diagnostics        ----
        self.f.remove_all_modules()
        self.f.add_module('Discharge', {})
        self.f.add_module('Heater', {})
        self.f.add_module('Magnetic field', {})
        self.f['MSI'].create_group('Not known')
        _map = self.map
        self.assertBasics(_map)

        # check correct diagnostics were mapped
        self.assertEqual(len(_map), 3)
        self.assertIn('Discharge', _map)
        self.assertIn('Heater', _map)
        self.assertIn('Magnetic field', _map)
        self.assertNotIn('Not known', _map)

        # delete unknown group
        del self.f['MSI/Not known']

        # the MSI group has a dataset                               ----
        self.f.remove_all_modules()
        self.f.add_module('Discharge', {})
        self.f.add_module('Heater', {})
        self.f.add_module('Magnetic field', {})
        data = np.empty((2, 100), dtype=np.float32)
        self.f['MSI'].create_dataset('A dataset', data=data)
        _map = self.map
        self.assertBasics(_map)

        # check correct diagnostics were mapped
        self.assertEqual(len(_map), 3)
        self.assertIn('Discharge', _map)
        self.assertIn('Heater', _map)
        self.assertIn('Magnetic field', _map)
        self.assertNotIn('A dataset', _map)

        # delete dataset
        del self.f['MSI/A dataset']

        # the MSI group has a mappable diagnostic                   ----
        # but mapping fails                                         ----
        self.f.remove_all_modules()
        self.f.add_module('Discharge', {})
        self.f.add_module('Heater', {})

        # remove a dataset from 'Discharge'
        # - this will cause mapping of 'Discharge' to fail
        #
        del self.f['MSI/Discharge/Discharge current']

        # check map
        _map = self.map
        self.assertBasics(_map)

        # check correct diagnostics were mapped
        self.assertEqual(len(_map), 1)
        self.assertIn('Heater', _map)
        self.assertNotIn('Discharge', _map)

    def assertBasics(self, msi_map: HDFMapMSI):
        # mapped object is a dictionary
        self.assertIsInstance(msi_map, dict)

        # all dict items are a mapping class
        for val in msi_map.values():
            self.assertIsInstance(val, HDFMapMSITemplate)

        # look for map attributes
        self.assertTrue(hasattr(msi_map, 'mappable_devices'))

        # check attribute types
        self.assertIsInstance(msi_map.mappable_devices, tuple)
Ejemplo n.º 10
0
class TestHDFMapControls(ut.TestCase):
    """Test class for HDFMapControls"""
    # What to test?
    # X  1. returned object is a dictionary
    # X  2. if input is not h5py.Group instance, then TypeError is
    #       raised
    # X  3. existence of:
    #       a. mappable_devices
    #          - check it's a tuple
    # X  4. data group has no sub-groups
    #       - dict is empty
    # X  5. data group has unknown & known control device sub-groups
    #       - only known group is added to dictionary
    #    6. data group has a known control sub-group, but mapping fails
    #       - failed map should not be added to to dict
    # X  7. all control devices are mappable, but not all mappable
    #       controls are included
    # X  8. data group has a dataset
    #

    def setUp(self):
        self.f = FauxHDFBuilder()

    def tearDown(self):
        self.f.cleanup()

    @property
    def map(self):
        """Map of Control Group"""
        return self.map_control(self.data_group)

    @property
    def data_group(self):
        """MSI group"""
        return self.f['Raw data + config']

    @staticmethod
    def map_control(group):
        """Mapping function"""
        return HDFMapControls(group)

    def test_not_h5py_group(self):
        """Test error if object to map is not h5py.Group"""
        with self.assertRaises(TypeError):
            self.map_control(None)

    def test_msi_scenarios(self):
        """
        Test various scenarios of mappable and non-mappable control
        device groups.
        """
        # the data group has NO control device groups               ----
        self.f.remove_all_modules()
        _map = self.map
        self.assertBasics(_map)
        self.assertEqual(_map, {})

        # the control group has all mappable devices                ----
        self.f.remove_all_modules()
        self.f.add_module('6K Compumotor', {})
        self.f.add_module('Waveform', {})
        _map = self.map
        self.assertBasics(_map)

        # check all controls were mapped
        self.assertEqual(len(_map), 2)
        self.assertIn('6K Compumotor', _map)
        self.assertIn('Waveform', _map)

        # the data group has mappable and unknown controls          ----
        self.f.remove_all_modules()
        self.f.add_module('6K Compumotor', {})
        self.f.add_module('Waveform', {})
        self.f['Raw data + config'].create_group('Not known')
        _map = self.map
        self.assertBasics(_map)

        # check correct diagnostics were mapped
        self.assertEqual(len(_map), 2)
        self.assertIn('6K Compumotor', _map)
        self.assertIn('Waveform', _map)
        self.assertNotIn('Not known', _map)

        # delete unknown group
        del self.f['Raw data + config/Not known']

        # the data group has a dataset                              ----
        self.f.remove_all_modules()
        self.f.add_module('Waveform', {})
        data = np.empty((2, 100), dtype=np.float32)
        self.f['Raw data + config'].create_dataset('A dataset',
                                                   data=data)
        _map = self.map
        self.assertBasics(_map)

        # check correct diagnostics were mapped
        self.assertEqual(len(_map), 1)
        self.assertIn('Waveform', _map)
        self.assertNotIn('A dataset', _map)

        # delete dataset
        del self.f['Raw data + config/A dataset']

        # the data group has a mappable control devices             ----
        # but mapping fails                                         ----
        self.f.remove_all_modules()
        self.f.add_module('6K Compumotor', {})
        self.f.add_module('Waveform', {})

        # remove a dataset from 'Waveform'
        # - this will cause mapping of 'Waveform' to fail
        #
        del self.f['Raw data + config/Waveform/config01']

        # check map
        _map = self.map
        self.assertBasics(_map)

        # check correct controls were mapped
        self.assertEqual(len(_map), 1)
        self.assertIn('6K Compumotor', _map)
        self.assertNotIn('Waveform', _map)

    def assertBasics(self, _map: HDFMapControls):
        # mapped object is a dictionary
        self.assertIsInstance(_map, dict)

        # all dict items are a mapping class
        for val in _map.values():
            self.assertIsInstance(val, (HDFMapControlTemplate,
                                        HDFMapControlCLTemplate))

        # look for map attributes
        self.assertTrue(
            hasattr(_map, 'mappable_devices'))

        # check attribute types
        self.assertIsInstance(_map.mappable_devices,
                              tuple)