def get_config(self, cb=None): """ Return this algorithm's current configuration. As algorithms are named, the configuration returned will be contained inside a sub-block whose name matches this algorithm's name in order to separate :param cb: An optional existing ConfigBlock instance to add this algorithm's configuration to. :type cb: ConfigBlock :return: This named algorithm's current configuration. If a config block was given to this method, the same config block is returned. :rtype: vital.ConfigBlock """ if cb is None: cb = ConfigBlock() self._call_cfunc( 'vital_algorithm_%s_get_type_config' % self.type_name(), [ctypes.c_char_p, self.C_TYPE_PTR, ConfigBlock.c_ptr_type()], [self.name, self, cb], ConfigBlock.c_ptr_type() ) return cb
def test_write_fail(self): cb = ConfigBlock() cb.set_value('foo', 'bar') nose.tools.assert_raises(VitalConfigBlockIoException, cb.write, '/not/valid')
def test_read_only_unset(self): cb = ConfigBlock() cb.set_value('a', '1') cb.mark_read_only('a') cb.unset_value('a') nose.tools.assert_true(cb.has_value('a')) nose.tools.assert_equal(cb.get_value('a'), '1')
def get_config(self, cb=None): """ Return this algorithm's current configuration. As algorithms are named, the configuration returned will be contained inside a sub-block whose name matches this algorithm's name in order to separate :param cb: An optional existing ConfigBlock instance to add this algorithm's configuration to. :type cb: ConfigBlock :return: This named algorithm's current configuration. If a config block was given to this method, the same config block is returned. :rtype: vital.ConfigBlock """ if cb is None: cb = ConfigBlock() self._call_cfunc( 'vital_algorithm_%s_get_type_config' % self.type_name(), [ctypes.c_char_p, self.C_TYPE_PTR, ConfigBlock.c_ptr_type()], [self.name, self, cb], ConfigBlock.c_ptr_type()) return cb
def test_construction(self): cb1 = ConfigBlock() nose.tools.assert_true(cb1._inst_ptr, "Received null pointer from " "ConfigBlock construction") cb2 = ConfigBlock("A Name") nose.tools.assert_true(cb2._inst_ptr, "Received a null pointer " "from named ConfigBlock " "construction.")
def test_name_access(self): cb = ConfigBlock() nose.tools.assert_equal(cb.name, "", "Default constructor should have an empty " "string name.") cb = ConfigBlock("FooBar") nose.tools.assert_equal(cb.name, "FooBar", "Named constructor didn't seem to retain name")
def test_get_value_bool_default(self): cb = ConfigBlock() nose.tools.assert_raises(VitalConfigBlockNoSuchValueException, cb.get_value_bool, 'not-a-key') nose.tools.assert_true(cb.get_value_bool('not-a-key', True)) nose.tools.assert_false(cb.get_value_bool('not-a-key', False))
def test_subblock_view_match(self): cb = ConfigBlock() bname = 'block' va = 'va' cb.set_value(bname, va) sb = cb.subblock_view(bname) keys = sb.available_keys() nose.tools.assert_equal(len(keys), 0)
def test_get_value_no_exist(self): cb = ConfigBlock() k1 = 'a' k2 = 'b' v2 = '2' nose.tools.assert_is_none(cb.get_value(k1)) nose.tools.assert_equal(cb.get_value(k2, v2), v2)
def test_read_only(self): cb = ConfigBlock() cb.set_value('a', '1') cb.mark_read_only('a') nose.tools.assert_equal(cb.get_value('a'), '1') cb.set_value('a', '2') nose.tools.assert_equal(cb.get_value('a'), '1')
def test_get_value_no_exist(self): cb = ConfigBlock() k1 = 'a' k2 = 'b' v2 = '2' nose.tools.assert_raises(VitalConfigBlockNoSuchValueException, cb.get_value, k1) nose.tools.assert_equal(cb.get_value(k2, v2), v2)
def test_subblock_view_prefix_match(self): cb = ConfigBlock() bname = 'block' ka = 'ka' va = 'va' # intentionally not adding block separator cb.set_value(bname + ka, va) sb = cb.subblock_view(bname) keys = sb.available_keys() nose.tools.assert_equal(len(keys), 0)
def test_set_conf(self): ci = ConvertImage('ci') nt.assert_false(ci) nt.assert_is_none(ci.impl_name()) c = ConfigBlock() c.set_value('ci:type', 'bypass') ci.set_config(c) nt.assert_true(ci) nt.assert_equal(ci.impl_name(), 'bypass')
def test_check_conf(self): ci = ConvertImage('ci') c = ConfigBlock() nt.assert_false(ci.check_config(c)) c.set_value('ci:type', '') nt.assert_false(ci.check_config(c)) c.set_value('ci:type', 'not_an_impl') nt.assert_false(ci.check_config(c))
def test_get_value_no_exist(self): cb = ConfigBlock() k1 = 'a' k2 = 'b' v2 = '2' nose.tools.assert_raises( VitalConfigBlockNoSuchValueException, cb.get_value, k1 ) nose.tools.assert_equal(cb.get_value(k2, v2), v2)
def test_get_value_nested(self): cb = ConfigBlock() k1 = 'a' k2 = 'b' v = 'c' cb.set_value(k1 + ConfigBlock.BLOCK_SEP + k2, v) nose.tools.assert_equal(cb.get_value(k1 + ConfigBlock.BLOCK_SEP + k2), v) sb = cb.subblock(k1) nose.tools.assert_equal(sb.get_value(k2), v)
def test_unset_value(self): cb = ConfigBlock() cb.set_value('a', '1') cb.set_value('b', '2') cb.unset_value('a') nose.tools.assert_false(cb.has_value('a')) nose.tools.assert_is_none(cb.get_value('a')) nose.tools.assert_equal(cb.get_value('b'), '2') nose.tools.assert_true(cb.has_value('b'))
def test_get_value_bool_default(self): cb = ConfigBlock() nose.tools.assert_raises( VitalConfigBlockNoSuchValueException, cb.get_value_bool, 'not-a-key' ) nose.tools.assert_true( cb.get_value_bool('not-a-key', True) ) nose.tools.assert_false( cb.get_value_bool('not-a-key', False) )
def default_config_block(): c = ConfigBlock() c.set_value( 'image_list_file', '', 'Path to an input file containing new-line separated paths to ' 'sequential image files') c.set_value( 'mask_list_file', '', 'Optional path to an input file containing new-line ' 'separated paths to mask images. This list should be ' 'parallel in association to files specified in ' '``image_list_file``. Mask image must be the same size as ' 'the image they are associated with.\n' '\n' 'Leave this blank if no image masking is desired.') c.set_value( 'output_tracks_file', '', 'Path to a file to write output tracks to. If this file ' 'exists, it will be overwritten.') image_reader, image_converter, feature_tracker = base_algorithms() image_reader.get_config(c) image_converter.get_config(c) feature_tracker.get_config(c) return c
def test_read_only_unset(self): cb = ConfigBlock() cb.set_value('a', '1') cb.mark_read_only('a') nose.tools.assert_raises(VitalConfigBlockReadOnlyException, cb.unset_value, 'a') nose.tools.assert_true(cb.has_value('a')) nose.tools.assert_equal(cb.get_value('a'), '1')
def test_set_value(self): cb = ConfigBlock() # Basic value string cb.set_value('foo', 'bar') # Should attempt casting non-string to string cb.set_value('bar', 124789) # Setting with a description cb.set_value('baz', 'a', "This is a description")
def test_read_valid_file(self): c = ConfigBlock.from_file( os.path.join(TEST_DATA_DIR, 'test_config-valid_file.txt')) nose.tools.assert_equal(len(c.available_keys()), 25) nose.tools.assert_equal(c.get_value('foo:bar'), 'baz') nose.tools.assert_equal(c.get_value('foo:things'), 'stuff') nose.tools.assert_equal(c.get_value('foo:sublevel:value'), 'cool things and stuff') nose.tools.assert_equal(c.get_value('second_block:has'), 'a value with spaces') nose.tools.assert_equal(c.get_value('second_block:more'), 'has a trailing comment') # relativepath value, interpreted against dir containing config file nose.tools.assert_equal( c.get_value('second_block:file'), os.path.join(TEST_DATA_DIR, 'options/test_Data.txt')) nose.tools.assert_equal(c.get_value('global_var'), '3.14159') nose.tools.assert_equal(c.get_value('global_var2'), '1.12') # Test read-only marking syntax nose.tools.assert_true(c.is_read_only('global_var')) nose.tools.assert_false(c.is_read_only('global_var2')) # Test variable reference parsing nose.tools.assert_equal(c.get_value('home'), os.path.join(os.environ['HOME'], 'homer')) nose.tools.assert_equal(c.get_value('config'), '3.14159') nose.tools.assert_equal(c.get_value('config2'), 'baz') nose.tools.assert_equal(c.get_value('local'), 'new value') # another relativepath value nose.tools.assert_equal(c.get_value('config_file'), os.path.join(TEST_DATA_DIR, 'inputs.txt'))
def get_config(self, cb=None): """ Return this algorithm's current configuration. As algorithms are named, the configuration returned will be contained inside a sub-block whose name matches this algorithm's name in order to separate :param cb: An optional existing ConfigBlock instance to add this algorithm's configuration to. :type cb: ConfigBlock :return: This named algorithm's current configuration. If a config block was given to this method, the same config block is returned. :rtype: vital.ConfigBlock """ algo_gtc = self.VITAL_LIB['vital_algorithm_%s_get_type_config' % self.type_name()] algo_gtc.argtypes = [ ctypes.c_char_p, self.C_TYPE_PTR, ConfigBlock.C_TYPE_PTR, VitalErrorHandle.C_TYPE_PTR ] algo_gtc.restype = ConfigBlock.C_TYPE_PTR if cb is None: cb = ConfigBlock() with VitalErrorHandle() as eh: algo_gtc(self.name, self, cb, eh) return cb
def test_get_value(self): cb = ConfigBlock() cb.set_value('a', 'b') cb.set_value('longer_value:foo', "BarBazThing") nose.tools.assert_equal(cb.get_value('a'), 'b') nose.tools.assert_equal(cb.get_value('longer_value:foo'), 'BarBazThing')
def test_available_keys(self): cb = ConfigBlock() cb.set_value("foo", 1) cb.set_value('bar', 'baz') r = cb.available_keys() nose.tools.assert_set_equal(set(r), {'foo', 'bar'}, "Returned key list was incorrect.")
def test_unset_value(self): cb = ConfigBlock() cb.set_value('a', '1') cb.set_value('b', '2') cb.unset_value('a') nose.tools.assert_false(cb.has_value('a')) nose.tools.assert_raises(VitalConfigBlockNoSuchValueException, cb.get_value, 'a') nose.tools.assert_equal(cb.get_value('b'), '2') nose.tools.assert_true(cb.has_value('b'))
def default_config_block(): c = ConfigBlock() c.set_value('image_list_file', '', 'Path to an input file containing new-line separated paths to ' 'sequential image files') c.set_value('mask_list_file', '', 'Optional path to an input file containing new-line ' 'separated paths to mask images. This list should be ' 'parallel in association to files specified in ' '``image_list_file``. Mask image must be the same size as ' 'the image they are associated with.\n' '\n' 'Leave this blank if no image masking is desired.') c.set_value('output_tracks_file', '', 'Path to a file to write output tracks to. If this file ' 'exists, it will be overwritten.') image_reader, image_converter, feature_tracker = base_algorithms() image_reader.get_config(c) image_converter.get_config(c) feature_tracker.get_config(c) return c
def test_check_conf(self): ci = ConvertImage('ci') c = ConfigBlock() nt.assert_false(ci.check_config(c)) c.set_value('ci:type', '') nt.assert_false(ci.check_config(c)) c.set_value('ci:type', 'not_an_impl') nt.assert_false(ci.check_config(c)) c.set_value('ci:type', 'bypass') nt.assert_true(ci.check_config(c))
def test_set_value_description(self): cb = ConfigBlock() bname = 'sub' ka = 'ka' kb = 'kb' kc = 'kc' va = 'va' vb = 'vb' vc = 'vc' da = 'da' db = 'db' cb.set_value(ka, va, da) cb.set_value(bname + ConfigBlock.BLOCK_SEP + kb, vb, db) cb.set_value(kc, vc) sb = cb.subblock('sub') nose.tools.assert_equal(cb.get_description(ka), da) nose.tools.assert_equal(sb.get_description(kb), db) nose.tools.assert_equal(cb.get_description(kc), "")
def test_merge_config(self): cb1 = ConfigBlock() cb2 = ConfigBlock() ka = 'ka' kb = 'kb' kc = 'kc' va = 'va' vb = 'vb' vc = 'vc' cb1.set_value(ka, va) cb1.set_value(kb, va) cb2.set_value(kb, vb) cb2.set_value(kc, vc) cb1.merge_config(cb2) nose.tools.assert_equal(cb1.get_value(ka), va) nose.tools.assert_equal(cb1.get_value(kb), vb) nose.tools.assert_equal(cb1.get_value(kc), vc)
def test_image_load_save_diff(self): fd, tmp_filename = tempfile.mkstemp() c = ConfigBlock() c.set_value('iio:type', 'vxl') iio = ImageIo('iio') iio.set_config(c) nt.assert_true(osp.isfile(self.test_image_filepath), "Couldn't find image file") ic_orig = iio.load(self.test_image_filepath) iio.save(ic_orig, tmp_filename) ic_test = iio.load(tmp_filename) nt.assert_equal(ic_orig.size(), ic_test.size()) nt.assert_equal(ic_orig.width(), ic_test.width()) nt.assert_equal(ic_orig.height(), ic_test.height()) nt.assert_equal(ic_orig.depth(), ic_test.depth()) os.remove(tmp_filename) os.close(fd)
def test_read_only_unset(self): cb = ConfigBlock() cb.set_value('a', '1') cb.mark_read_only('a') nose.tools.assert_raises( VitalConfigBlockReadOnlyException, cb.unset_value, 'a' ) nose.tools.assert_true(cb.has_value('a')) nose.tools.assert_equal(cb.get_value('a'), '1')
def test_subblock_nested(self): cb = ConfigBlock() block_name = 'block' other_name = 'other' nestd_name = block_name + ConfigBlock.BLOCK_SEP + other_name ka = 'ka' kb = 'kb' va = 'va' vb = 'vb' cb.set_value(nestd_name + ConfigBlock.BLOCK_SEP + ka, va) cb.set_value(nestd_name + ConfigBlock.BLOCK_SEP + kb, vb) sb = cb.subblock(nestd_name) nose.tools.assert_true(sb.has_value(ka)) nose.tools.assert_equal(sb.get_value(ka), va) nose.tools.assert_true(sb.has_value(kb)) nose.tools.assert_equal(sb.get_value(kb), vb)
def cli_main(): """ Returns: 0 - Success 1 - Configuration invalid 2 - Tracking failed """ import optparse logging.getLogger().setLevel(logging.INFO) log = logging.getLogger("cli_main") parser = optparse.OptionParser() parser.add_option("-c", "--config", help="Path to the configuration file to use.") parser.add_option("-o", "--output-config", help="Output a configuration file for the current " "configuration to the specified file path.") opts, args = parser.parse_args() if opts.config: opts.config = os.path.abspath(os.path.expanduser(opts.config)) if opts.output_config: opts.output_config = os.path.abspath( os.path.expanduser(opts.output_config)) tft = TrackFeaturesTool() if opts.config: log.info("Setting configuration file: %s", opts.config) tft.set_configuration(ConfigBlock.from_file(opts.config)) if opts.output_config: log.info("Writing output configuration file: %s", opts.output_config) tft.get_configuration().write(opts.output_config) if not tft.validate_configuration(): log.warning("Current configuration insufficient for running the " "tool") return 0 # Error out if current configuration not valid if not tft.validate_configuration(): log.error("Current configuration insufficient for running the tool") return 1 if tft.track_images(): return 0 else: return 2
def test_unset_value(self): cb = ConfigBlock() cb.set_value('a', '1') cb.set_value('b', '2') cb.unset_value('a') nose.tools.assert_false(cb.has_value('a')) nose.tools.assert_raises( VitalConfigBlockNoSuchValueException, cb.get_value, 'a' ) nose.tools.assert_equal(cb.get_value('b'), '2') nose.tools.assert_true(cb.has_value('b'))
def base_algorithms(c=ConfigBlock()): """ Determine the algorithms and algorithm names used in this utility :type c: vital.ConfigBlock """ iio = ImageIo('image_reader') iio.set_config(c) ci = ConvertImage('convert_image') ci.set_config(c) tf = TrackFeatures('feature_tracker') tf.set_config(c) return iio, ci, tf
def cli_main(): """ Returns: 0 - Success 1 - Configuration invalid 2 - Tracking failed """ import optparse logging.getLogger().setLevel(logging.INFO) log = logging.getLogger("cli_main") parser = optparse.OptionParser() parser.add_option("-c", "--config", help="Path to the configuration file to use.") parser.add_option("-o", "--output-config", help="Output a configuration file for the current " "configuration to the specified file path.") opts, args = parser.parse_args() if opts.config: opts.config = os.path.abspath(os.path.expanduser(opts.config)) if opts.output_config: opts.output_config = os.path.abspath(os.path.expanduser(opts.output_config)) tft = TrackFeaturesTool() if opts.config: log.info("Setting configuration file: %s", opts.config) tft.set_configuration(ConfigBlock.from_file(opts.config)) if opts.output_config: log.info("Writing output configuration file: %s", opts.output_config) tft.get_configuration().write(opts.output_config) if not tft.validate_configuration(): log.warning("Current configuration insufficient for running the " "tool") return 0 # Error out if current configuration not valid if not tft.validate_configuration(): log.error("Current configuration insufficient for running the tool") return 1 if tft.track_images(): return 0 else: return 2
def check_config(self, cb): """ Check the given configuration block for valid algorithm configuration :param cb: Configuration to check. :type cb: ConfigBlock :return: True if the given configuration block contains a valid configuration for this algorithm type and implementation. :rtype: bool """ return self._call_cfunc( 'vital_algorithm_%s_check_type_config' % self.type_name(), [ctypes.c_char_p, ConfigBlock.c_ptr_type()], [self.name, cb], ctypes.c_bool)
def check_config(self, cb): """ Check the given configuration block for valid algorithm configuration :param cb: Configuration to check. :type cb: ConfigBlock :return: True if the given configuration block contains a valid configuration for this algorithm type and implementation. :rtype: bool """ return self._call_cfunc( 'vital_algorithm_%s_check_type_config' % self.type_name(), [ctypes.c_char_p, ConfigBlock.c_ptr_type()], [self.name, cb], ctypes.c_bool )
def test_subblock(self): cb = ConfigBlock() block_name = 'block' other_name = 'other_block' ka = 'keya' kb = 'keyb' kc = 'keyc' va = 'va' vb = 'vb' vc = 'vc' cb.set_value(block_name + ConfigBlock.BLOCK_SEP + ka, va) cb.set_value(block_name + ConfigBlock.BLOCK_SEP + kb, vb) cb.set_value(other_name + ConfigBlock.BLOCK_SEP + kc, vc) sb = cb.subblock(block_name) nose.tools.assert_true(sb.has_value(ka)) nose.tools.assert_equal(sb.get_value(ka), va) nose.tools.assert_true(sb.has_value(kb)) nose.tools.assert_equal(sb.get_value(kb), vb) nose.tools.assert_false(sb.has_value(kc))
def get_default_config(): c = ConfigBlock("track_features") c.set_value( "image_list_file", "", "Path to an input file containing new-line separated paths " "to sequential image files") c.set_value( "mask_list_file", "", "Optional path to an input file containing new-line " "separated paths to mask images. This list should be " "parallel in association to files specified in " "``image_list_file``. Mask image must be the same size as " "the image they are associated with.\n" "\n" "Leave this blank if no image masking is desired.") c.set_value( "invert_masks", "false", "If true, all mask images will be inverted after loading. " "This is useful if mask images read in use positive " "values to indicated masked areas instead of non-masked " "areas.") c.set_value( "expect_multichannel_masks", "false", "A majority of the time, mask images are a single channel, " "however it is feasibly possible that certain " "implementations may use multi-channel masks. If this is " "true we will expect multiple-channel mask images, " "warning when a single-channel mask is provided. If this " "is false we error upon seeing a multi-channel mask " "image.") c.set_value( "output_tracks_file", "", "Path to a file to write output tracks to. If this " "file exists, it will be overwritten.") # Required algorithm does not have an implemented interface yet # c.set_value("output_homography_file", "", # "Optional path to a file to write source-to-reference " # "homographies for each frame. Leave blank to disable this " # "output. The output_homography_generator algorithm type " # "only needs to be set if this is set.") return c
def test_has_value(self): cb = ConfigBlock() cb.set_value('foo', 'bar') cb.set_value('bar', 124789) cb.set_value('baz', 'a', "This is a description") nose.tools.assert_true(cb.has_value("foo")) nose.tools.assert_true(cb.has_value('bar')) nose.tools.assert_true(cb.has_value('baz')) nose.tools.assert_false(cb.has_value('a')) nose.tools.assert_false(cb.has_value('not a value'))
def test_get_value_bool(self): cb = ConfigBlock() cb.set_value('a', 'true') nose.tools.assert_true(cb.get_value_bool('a')) cb.set_value('b', 'false') nose.tools.assert_false(cb.get_value_bool('b')) cb.set_value('a', 'yes') nose.tools.assert_true(cb.get_value_bool('a')) cb.set_value('b', 'no') nose.tools.assert_false(cb.get_value_bool('b'))
def get_default_config(): c = ConfigBlock("track_features") c.set_value("image_list_file", "", "Path to an input file containing new-line separated paths " "to sequential image files") c.set_value("mask_list_file", "", "Optional path to an input file containing new-line " "separated paths to mask images. This list should be " "parallel in association to files specified in " "``image_list_file``. Mask image must be the same size as " "the image they are associated with.\n" "\n" "Leave this blank if no image masking is desired.") c.set_value("invert_masks", "false", "If true, all mask images will be inverted after loading. " "This is useful if mask images read in use positive " "values to indicated masked areas instead of non-masked " "areas.") c.set_value("expect_multichannel_masks", "false", "A majority of the time, mask images are a single channel, " "however it is feasibly possible that certain " "implementations may use multi-channel masks. If this is " "true we will expect multiple-channel mask images, " "warning when a single-channel mask is provided. If this " "is false we error upon seeing a multi-channel mask " "image.") c.set_value("output_tracks_file", "", "Path to a file to write output tracks to. If this " "file exists, it will be overwritten.") # Required algorithm does not have an implemented interface yet # c.set_value("output_homography_file", "", # "Optional path to a file to write source-to-reference " # "homographies for each frame. Leave blank to disable this " # "output. The output_homography_generator algorithm type " # "only needs to be set if this is set.") return c
def test_subblock_view_nested(self): cb = ConfigBlock() b_name = 'block' o_name = 'other_block' n_name = b_name + ConfigBlock.BLOCK_SEP + o_name ka = 'ka' kb = 'kb' kc = 'kc' va = 'va' vb = 'vb' vc = 'vc' cb.set_value(n_name + ConfigBlock.BLOCK_SEP + ka, va) cb.set_value(n_name + ConfigBlock.BLOCK_SEP + kb, vb) cb.set_value(o_name + ConfigBlock.BLOCK_SEP + kc, vc) sb = cb.subblock_view(n_name) nose.tools.assert_true(sb.has_value(ka)) nose.tools.assert_false(sb.has_value(kc)) cb.set_value(n_name + ConfigBlock.BLOCK_SEP + ka, vb) nose.tools.assert_equal(sb.get_value(ka), vb) sb.set_value(ka, va) nose.tools.assert_equal(cb.get_value(n_name + ConfigBlock.BLOCK_SEP + ka), va) sb.unset_value(kb) nose.tools.assert_false(cb.has_value(n_name + ConfigBlock.BLOCK_SEP + kb)) cb.set_value(n_name + ConfigBlock.BLOCK_SEP + kc, vc) sb_keys = sb.available_keys() nose.tools.assert_set_equal(set(sb_keys), {ka, kc})