Esempio n. 1
0
def generate_config(config=None):
    """
    Generate a sample configuration object.

    :param config: An optional configuration object to add to.
    :type config: None or SafeConfigCommentParser

    :return: Generated configuration object
    :rtype: SafeConfigCommentParser

    """
    log = logging.getLogger()

    if config is None:
        log.debug('generating new config object')
        config = SafeConfigCommentParser()

    log.info("Adding vcd_scheduler section...")
    sect = MPIS_CONFIG_SECT
    config.add_section(sect)
    config.set(
        sect, 'image_directory', '# REQUIRED',
        "The root directory where imagery will be extracted and stored. "
        "This is a common structure across any descriptors that want to "
        "extract imagery.")
    config.set(sect, 'run_work_directory', '# REQUIRED',
               "The base working directory for this run.")
    config.set(
        sect, 'video_work_list', '# REQUIRED',
        "A test time with a new-line separated list of video files to "
        "process.")
    config.set(sect, 'log_dir', "%(run_work_directory)s/logs",
               "Directory where log files from the run are to be stored.")
    config.set(
        sect, 'target_vcd_store', 'SQLiteVCDStore.db',
        "The sqlite3 database file results will be accumulated into. If "
        "this is given as a relative path it will be considered "
        "relative to the provided work directory.")
    config.set(
        sect, 'vcd_store_overwrite', 'false',
        "When the server node attempts to store VCDStoreElement "
        "objects, overwrite existing entries if found. Else, if this is "
        "false, favor the existing entries and roll back the insertion "
        "attempt.")

    # TODO: [generate_config] (see below)
    # This tells the vcd_scheduler which descriptor client module to load
    # This should also tell us what VCDWorker implementation to use. This
    #   requires that we shift over to using the VCDWorker implementation
    #   structure instead of the very similar function thing we currently have
    #   going on...
    # Should be straight forward to convert current stuff to VCDWorker impl.
    #   Need to modify VCDWorker impls with lessons learned here.
    # avail_modes = get_descriptor_client_methods().keys()
    descr_modules = get_descriptor_modules()
    config.set(
        sect, 'descriptor_mode', '# REQUIRED',
        "The descriptor mode to run in. This defined which descriptor "
        "will process the videos listed in the given work list file.\n"
        "\n"
        "The available modes are as follows:\n"
        " - '%s'" % "'\n - '".join(descr_modules.keys()))

    # Append descriptor module configs to this one
    for name, m in descr_modules.items():
        log.info("Adding '%s' module section...", name)
        m.generate_config(config)

    return config
Esempio n. 2
0
def generate_config(config=None):
    """
    Generate a sample configuration object.

    :param config: An optional configuration object to add to.
    :type config: None or SafeConfigCommentParser

    :return: Generated configuration object
    :rtype: SafeConfigCommentParser

    """
    log = logging.getLogger()

    if config is None:
        log.debug("generating new config object")
        config = SafeConfigCommentParser()

    log.info("Adding vcd_scheduler section...")
    sect = MPIS_CONFIG_SECT
    config.add_section(sect)
    config.set(
        sect,
        "image_directory",
        "# REQUIRED",
        "The root directory where imagery will be extracted and stored. "
        "This is a common structure across any descriptors that want to "
        "extract imagery.",
    )
    config.set(sect, "run_work_directory", "# REQUIRED", "The base working directory for this run.")
    config.set(
        sect,
        "video_work_list",
        "# REQUIRED",
        "A test time with a new-line separated list of video files to " "process.",
    )
    config.set(
        sect, "log_dir", "%(run_work_directory)s/logs", "Directory where log files from the run are to be stored."
    )
    config.set(
        sect,
        "target_vcd_store",
        "SQLiteVCDStore.db",
        "The sqlite3 database file results will be accumulated into. If "
        "this is given as a relative path it will be considered "
        "relative to the provided work directory.",
    )
    config.set(
        sect,
        "vcd_store_overwrite",
        "false",
        "When the server node attempts to store VCDStoreElement "
        "objects, overwrite existing entries if found. Else, if this is "
        "false, favor the existing entries and roll back the insertion "
        "attempt.",
    )

    # TODO: [generate_config] (see below)
    # This tells the vcd_scheduler which descriptor client module to load
    # This should also tell us what VCDWorker implementation to use. This
    #   requires that we shift over to using the VCDWorker implementation
    #   structure instead of the very similar function thing we currently have
    #   going on...
    # Should be straight forward to convert current stuff to VCDWorker impl.
    #   Need to modify VCDWorker impls with lessons learned here.
    # avail_modes = get_descriptor_client_methods().keys()
    descr_modules = get_descriptor_modules()
    config.set(
        sect,
        "descriptor_mode",
        "# REQUIRED",
        "The descriptor mode to run in. This defined which descriptor "
        "will process the videos listed in the given work list file.\n"
        "\n"
        "The available modes are as follows:\n"
        " - '%s'" % "'\n - '".join(descr_modules.keys()),
    )

    # Append descriptor module configs to this one
    for name, m in descr_modules.items():
        log.info("Adding '%s' module section...", name)
        m.generate_config(config)

    return config
Esempio n. 3
0
    def test_controller_interaction(self):
        print 'poke'
        # Dummy classes representing function of intended components
        class Controller (Process):
            """ Reads input from queue, exiting when receives None
            """
            def __init__(self, data_queue):
                super(Controller, self).__init__(name="controller")
                self._queue = data_queue
            def run(self):
                running = True
                while running:
                    print "[Controller] waiting for data..."
                    elem = self._queue.get()
                    print "[Controller] received:", type(elem), elem
                    if elem is None:
                        running = False
        class DummyAsw (Process):
            """ sends dk to queue on separate process
            """
            def __init__(self, dk, data_queue):
                super(DummyAsw, self).__init__()
                self._dk = dk
                self._queue = data_queue
            def run(self):
                self._queue.put(self._dk)
        def generate_dks(mgr):
            """ generated some distance kernels to test with given a connected
                FeatureManager
            """
            c_fmm = mgr.get_common_fmm()
            if 'test' in c_fmm.get_feature_types():
                c_fmm.remove('test')
            c_fmm.initialize_from_files('test', self.sym_cids_file,
                                        self.sym_bg_flags,
                                        self.sym_feat_mat_f,
                                        self.sym_dk_mat_f)
            dk1 = c_fmm.get_distance_kernel('test')
            dk2 = mgr.symmetric_dk_from_file(self.sym_cids_file,
                                             self.sym_dk_mat_f,
                                             self.sym_bg_flags)
            return dk1, dk2

        # Set-up and start the extra-process feature manager server
        host = 'localhost'
        port = 54321
        addr = (host, port)
        auth_key = "foobar"
        config_file = osp.join(self.work_dir,
                               'controller_interaction_server.ini')
        config = SafeConfigCommentParser()
        config.add_section('server')
        config.set('server', 'port', str(port))
        config.set('server', 'authkey', auth_key)
        with open(config_file, 'w') as ofile:
            # noinspection PyTypeChecker
            config.write(ofile)
        p = subprocess.Popen(['FeatureManagerServer', '-c', config_file])
        # wait a sec for the server to start/fail
        time.sleep(1)  # should be sufficient...
        self.assertIsNone(p.poll(), "Server process shutdown prematurely. "
                                    "Check reported error on console.")

        initFeatureManagerConnection(addr, auth_key)
        mgr = getFeatureManager(addr)

        # Initialize and start dummy controller process
        q = Queue()
        c = Controller(q)
        c.start()

        # generated DistanceKernels and dummy ASW processes
        dk1, dk2 = generate_dks(mgr)
        asw1 = DummyAsw(dk1, q)
        asw2 = DummyAsw(dk2, q)

        # Running the two dummy asw processes should cause no errors in either
        # dummy ASW or the dummy Controller
        asw1.start()
        asw1.join()
        asw2.start()
        asw2.join()

        # shutdown controller
        q.put(None)
        c.join()
        print "C exitcode:", c.exitcode

        # Clean-up
        # Need to call del on some things else we would get hung up in decref
        # call to remove server at function/process exit.
        del dk1, dk2, asw1, asw2
        os.remove(config_file)
        removeFeatureManagerConnection(addr)
        p.terminate()
        p.poll()

        self.assertEqual(c.exitcode, 0, "Controller dummy did not exit cleanly")
        del c
Esempio n. 4
0
    def test_fm_external_server(self):
        print "==================================================="
        print "Testing use of external server with update function"
        print "==================================================="

        host = 'localhost'
        port = 54321
        addr = (host, port)
        auth_key = "foobar"

        # Trying to connect to these right away should result in a timeout
        # in the underlying proxy.
        self.assertRaises(
            Exception,
            initFeatureManagerConnection,
            addr, auth_key
        )

        # Start the server at the specified addr
        config_file = osp.join(self.work_dir, 'test_server_config.ini')
        config = SafeConfigCommentParser()
        config.add_section('server')
        config.set('server', 'port', str(port))
        config.set('server', 'authkey', auth_key)
        with open(config_file, 'w') as ofile:
            # noinspection PyTypeChecker
            config.write(ofile)
        p = subprocess.Popen(['FeatureManagerServer', '-c', config_file])
        # wait a sec for the server to start/fail
        time.sleep(1)  # should be sufficient...
        self.assertIsNone(p.poll(), "Server process shutdown prematurely. "
                                    "Check reported error on console.")

        # Now we should be able to connect, create a FeatureMemory[Map] and
        # successfully go through the update process.
        from multiprocessing.connection import AuthenticationError
        self.assertRaises(
            AuthenticationError,
            initFeatureManagerConnection,
            addr, "not the right key"
        )

        # Shouldn't be in there yet as its not initialized
        self.assertRaises(
            KeyError,
            getFeatureManager,
            addr
        )

        initFeatureManagerConnection(addr, auth_key)

        # should get a ValueError when trying to init the same address more than
        # once.
        self.assertRaises(
            ValueError,
            initFeatureManagerConnection,
            addr, auth_key
        )

        mgr = getFeatureManager(addr)

        # Create a feature map->featureMemory and pass through update process
        f_type = 'test'
        cid_file = osp.join(self.data_dir, 'symmetric_clipids.txt')
        bg_flags_file = osp.join(self.data_dir, 'symmetric_bgflags.txt')
        feature_file = osp.join(self.data_dir, 'symmetric_feature.npy')
        kernel_file = osp.join(self.data_dir, 'symmetric_distance_kernel.npy')

        #: :type: FeatureMemoryMap
        fmm = mgr.get_common_fmm()
        fmm.initialize_from_files(f_type, cid_file, bg_flags_file, feature_file,
                                  kernel_file)
        fm = fmm.get_feature_memory(f_type)
        self._update_test_helper(fm)

        # Clean up
        # Need to call del else we would get hung up in decref call to remove
        # server at function/process exit.
        del fm, fmm
        p.terminate()
        os.remove(config_file)
        removeFeatureManagerConnection(addr)
Esempio n. 5
0
    def generate_config(cls, config=None):
        """
        Generate, define and return a configuration object for this descriptor
        worker.

        :param config: An optionally existing configuration object to update.
        :type config: None or SafeConfigCommentParser
        :return: Updated configuration object with this descriptor's specific
            configuration parameters.
        :rtype: SafeConfigCommentParser

        """
        if config is None:
            config = SafeConfigCommentParser()

        # If the config sections for the utility methods are not present, add
        # them and their options.
        if not config.has_section(cls.EXTRACTOR_CONFIG_SECT):
            sect = cls.EXTRACTOR_CONFIG_SECT
            config.add_section(sect,
                               "Options controlling how frames are extracted "
                               "from videos when requested.\n"
                               "\n"
                               "The following are standard frame extraction "
                               "configurations for configurable descriptor "
                               "modules (in offset,interval,max_duration "
                               "value order):\n"
                               "    - colordescriptor -> (0, 2, 10)\n"
                               "    - subattributes   -> (3, 4, 0)\n")
            config.set(sect, 'frame_extractor_exe', 'frame_extractor',
                       "The frame_extractor executable to use")
            config.set(sect, 'start_offset_seconds', '0.0',
                       "The number of seconds after the start of the video to "
                       "start extracting frames. This may be 0 or not provided "
                       "to indicate no offset.")
            config.set(sect, 'second_interval', '2.0',
                       "Extract frames, after the provided offset, every N "
                       "seconds, where N is the value provided here. This may "
                       "be floating point. This may be 0 or not provided to "
                       "extract all frames after the given offset.")
            config.set(sect, 'max_duration_minutes', '10.0',
                       "Maximum time which we are not to extract frames past. "
                       "This should be provided in decimal minutes. This may "
                       "be not provided (no value given), or set to 0, to "
                       "indicate no maximum duration limit. ")

        if not config.has_section(cls.PROBE_CONFIG_SECT):
            sect = cls.PROBE_CONFIG_SECT
            config.add_section(sect)
            config.set(sect, 'ffprobe_exe', 'ffprobe',
                       "The ffmpeg ffprobe executable to use when probing for "
                       "video metadata.")
            config.set(sect, 'use_TBR_fallback', 'false',
                       "Use or don't use the TBR value when the FPS value is "
                       "not present when probing video metadata.")

        return config
Esempio n. 6
0
    def generate_config(cls, config=None):
        """
        Generate, define and return a configuration object for this descriptor
        worker.

        :param config: An optionally existing configuration object to update.
        :type config: None or SafeConfigCommentParser
        :return: Updated configuration object with this descriptor's specific
            configuration parameters.
        :rtype: SafeConfigCommentParser

        """
        if config is None:
            config = SafeConfigCommentParser()

        # If the config sections for the utility methods are not present, add
        # them and their options.
        if not config.has_section(cls.EXTRACTOR_CONFIG_SECT):
            sect = cls.EXTRACTOR_CONFIG_SECT
            config.add_section(
                sect, "Options controlling how frames are extracted "
                "from videos when requested.\n"
                "\n"
                "The following are standard frame extraction "
                "configurations for configurable descriptor "
                "modules (in offset,interval,max_duration "
                "value order):\n"
                "    - colordescriptor -> (0, 2, 10)\n"
                "    - subattributes   -> (3, 4, 0)\n")
            config.set(sect, 'frame_extractor_exe', 'frame_extractor',
                       "The frame_extractor executable to use")
            config.set(
                sect, 'start_offset_seconds', '0.0',
                "The number of seconds after the start of the video to "
                "start extracting frames. This may be 0 or not provided "
                "to indicate no offset.")
            config.set(
                sect, 'second_interval', '2.0',
                "Extract frames, after the provided offset, every N "
                "seconds, where N is the value provided here. This may "
                "be floating point. This may be 0 or not provided to "
                "extract all frames after the given offset.")
            config.set(
                sect, 'max_duration_minutes', '10.0',
                "Maximum time which we are not to extract frames past. "
                "This should be provided in decimal minutes. This may "
                "be not provided (no value given), or set to 0, to "
                "indicate no maximum duration limit. ")

        if not config.has_section(cls.PROBE_CONFIG_SECT):
            sect = cls.PROBE_CONFIG_SECT
            config.add_section(sect)
            config.set(
                sect, 'ffprobe_exe', 'ffprobe',
                "The ffmpeg ffprobe executable to use when probing for "
                "video metadata.")
            config.set(
                sect, 'use_TBR_fallback', 'false',
                "Use or don't use the TBR value when the FPS value is "
                "not present when probing video metadata.")

        return config