Esempio n. 1
0
    def test_set_name(self):
        algo_name = 'ci'
        other_name = "other_name"

        ci = ConvertImage(algo_name)
        nt.assert_equal(ci.name, algo_name)
        ci.set_name(other_name)
        nt.assert_not_equal(ci.name, algo_name)
        nt.assert_equal(ci.name, other_name)
Esempio n. 2
0
 def test_clone(self):
     # inst_ptr will be null for both
     ci1 = ConvertImage('ci')
     ci2 = ci1.clone()
     nt.assert_false(ci1)
     nt.assert_false(ci2)
     nt.assert_not_equal(ci1.c_pointer, ci2.c_pointer)
     # They should both be null
     nt.assert_equal(mem_address(ci1.c_pointer), mem_address(ci2.c_pointer))
Esempio n. 3
0
    def test_get_conf(self):
        ci = ConvertImage('ci')
        c = ci.get_config()
        nt.assert_list_equal(c.available_keys(), ['ci:type'])
        nt.assert_equal(c.get_value('ci:type'), '')

        ci = ConvertImage.create('ci', 'bypass')
        c = ci.get_config()
        nt.assert_equal(c.get_value('ci:type'), 'bypass')
Esempio n. 4
0
    def test_get_conf(self):
        ci = ConvertImage('ci')
        c = ci.get_config()
        nt.assert_list_equal(c.available_keys(), ['ci:type'])
        nt.assert_equal(c.get_value('ci:type'), '')

        ci = ConvertImage.create('ci', 'bypass')
        c = ci.get_config()
        nt.assert_equal(c.get_value('ci:type'), 'bypass')
Esempio n. 5
0
    def test_set_name(self):
        algo_name = 'ci'
        other_name = "other_name"

        ci = ConvertImage(algo_name)
        nt.assert_equal(ci.name, algo_name)
        ci.set_name(other_name)
        nt.assert_not_equal(ci.name, algo_name)
        nt.assert_equal(ci.name, other_name)
Esempio n. 6
0
 def test_clone(self):
     # inst_ptr will be null for both
     ci1 = ConvertImage('ci')
     ci2 = ci1.clone()
     nt.assert_false(ci1)
     nt.assert_false(ci2)
     nt.assert_not_equal(ci1.c_pointer, ci2.c_pointer)
     # They should both be null
     nt.assert_equal(mem_address(ci1.c_pointer), mem_address(ci2.c_pointer))
Esempio n. 7
0
    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))
Esempio n. 8
0
    def test_check_conf(self):
        ci = ConvertImage('ci')
        c = config_block()
        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))
Esempio n. 9
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')
Esempio n. 10
0
    def __init__(self):
        AlgorithmPluginManager.register_plugins()

        # Algorithms
        self.algo_convert_img = ConvertImage("convert_image")
        self.algo_image_io = ImageIo("image_reader")
        self.algo_track_features = TrackFeatures("feature_tracker")

        # Other tool variables
        self.image_list_filepath = None
        self.mask_list_filepath = None
        self.invert_masks = False
        self.expect_multichannel_masks = False
        self.output_tracks_filepath = None
Esempio n. 11
0
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
Esempio n. 12
0
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
Esempio n. 13
0
 def test_clone(self):
     ci1 = ConvertImage.create('ci', 'bypass')
     ci2 = ci1.clone()
     nt.assert_true(ci1)
     nt.assert_true(ci2)
     nt.assert_not_equal(ci1.c_pointer, ci2.c_pointer)
     nt.assert_not_equal(mem_address(ci1.c_pointer),
                                 mem_address(ci2.c_pointer))
Esempio n. 14
0
    def test_from_c_ptr_no_name(self):
        nt.assert_raises(
            TypeError,
            ConvertImage,
            from_cptr=ConvertImage.C_TYPE_PTR(),
        )

        nt.assert_raises(ValueError, ConvertImage, None)
Esempio n. 15
0
 def test_clone(self):
     ci1 = ConvertImage.create('ci', 'bypass')
     ci2 = ci1.clone()
     nt.assert_true(ci1)
     nt.assert_true(ci2)
     nt.assert_not_equal(ci1.c_pointer, ci2.c_pointer)
     nt.assert_not_equal(mem_address(ci1.c_pointer),
                         mem_address(ci2.c_pointer))
Esempio n. 16
0
    def test_convert(self):
        ic1 = ImageContainer(Image())
        ci = ConvertImage.create('ci', 'bypass')
        ic2 = ci.convert(ic1)

        nt.assert_not_equal(ic1, ic2)
        nt.assert_not_equal(ic1.c_pointer, ic2.c_pointer)
        nt.assert_equal(hex(mem_address(ic1.c_pointer)),
                        hex(mem_address(ic2.c_pointer)))
Esempio n. 17
0
    def test_convert(self):
        ic1 = ImageContainer(Image())
        ci = ConvertImage.create('ci', 'bypass')
        ic2 = ci.convert(ic1)

        nt.assert_not_equal(ic1, ic2)
        nt.assert_not_equal(ic1.c_pointer, ic2.c_pointer)
        nt.assert_equal(hex(mem_address(ic1.c_pointer)),
                        hex(mem_address(ic2.c_pointer)))
Esempio n. 18
0
    def __init__(self):
        apm.register_plugins()

        # Algorithms
        self.algo_convert_img = ConvertImage("convert_image")
        self.algo_image_io = ImageIo("image_reader")
        self.algo_track_features = TrackFeatures("feature_tracker")

        # Other tool variables
        self.image_list_filepath = None
        self.mask_list_filepath = None
        self.invert_masks = False
        self.expect_multichannel_masks = False
        self.output_tracks_filepath = None
Esempio n. 19
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')
Esempio n. 20
0
 def test_clone_empty(self):
     ci_empty = ConvertImage('ci')
     ci_empty2 = ci_empty.clone()
     nt.assert_false(ci_empty)
     nt.assert_false(ci_empty2)
Esempio n. 21
0
 def test_from_c_ptr_no_name(self):
     nt.assert_raises(
         ValueError,
         ConvertImage.from_c_pointer,
         ConvertImage.C_TYPE_PTR(),
     )
Esempio n. 22
0
 def test_from_c_ptr_null(self):
     ci = ConvertImage.from_c_pointer(
         ConvertImage.C_TYPE_PTR(),
         name='ci'
     )
     nt.assert_false(ci.c_pointer)
Esempio n. 23
0
 def test_impl_name(self):
     ci_empty = ConvertImage('ci')
     nt.assert_is_none(ci_empty.impl_name())
     ci_bypass = ConvertImage.create('ci', 'bypass')
     nt.assert_equal(ci_bypass.impl_name(), 'bypass')
Esempio n. 24
0
class TrackFeaturesTool(object):
    @property
    def log(self):
        return logging.getLogger("TrackFeaturesTool")

    def __init__(self):
        AlgorithmPluginManager.register_plugins()

        # Algorithms
        self.algo_convert_img = ConvertImage("convert_image")
        self.algo_image_io = ImageIo("image_reader")
        self.algo_track_features = TrackFeatures("feature_tracker")

        # Other tool variables
        self.image_list_filepath = None
        self.mask_list_filepath = None
        self.invert_masks = False
        self.expect_multichannel_masks = False
        self.output_tracks_filepath = None

    def get_configuration(self):
        """
        :return: the current tool configuration
        :rtype: ConfigBlock
        """
        c = ConfigBlock("track_features")
        c.set_value(
            "image_list_file", self.image_list_filepath or "",
            "Path to an input file containing new-line separated paths "
            "to sequential image files")
        c.set_value(
            "mask_list_file", self.mask_list_filepath or "",
            "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",
            str(self.invert_masks).lower(),
            "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",
            str(self.expect_multichannel_masks).lower(),
            "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", self.output_tracks_filepath or "",
            "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",
        #             self.output_homography_filepath or "",
        #             "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.")

        self.algo_convert_img.get_config(c)
        self.algo_image_io.get_config(c)
        self.algo_track_features.get_config(c)

        return c

    def set_configuration(self, config):
        """
        Set the tool configuration
        :param config: The configuration to set
        :type config: ConfigBlock
        """
        self.algo_convert_img.set_config(config)
        self.algo_image_io.set_config(config)
        self.algo_track_features.set_config(config)

        abspath = lambda p: os.path.abspath(os.path.expanduser(p))

        self.image_list_filepath = config.get_value('image_list_file',
                                                    self.image_list_filepath)
        if self.image_list_filepath:
            self.image_list_filepath = abspath(self.image_list_filepath)
        self.mask_list_filepath = config.get_value('mask_list_file',
                                                   self.mask_list_filepath)
        if self.mask_list_filepath:
            self.mask_list_filepath = abspath(self.mask_list_filepath)
        self.invert_masks = config.get_value_bool('invert_masks',
                                                  self.invert_masks)
        self.expect_multichannel_masks = \
            config.get_value_bool('expect_multichannel_masks',
                            self.expect_multichannel_masks)
        self.output_tracks_filepath = \
            config.get_value('output_tracks_file', self.output_tracks_filepath)
        if self.output_tracks_filepath:
            self.output_tracks_filepath = abspath(self.output_tracks_filepath)

    def validate_configuration(self):
        """
        Check the current configuration for validity
        :return: True if valid, false if not.
        :type: bool
        """
        if not self.image_list_filepath:
            self.log.error("No image list file provided")
            return False
        if not os.path.isfile(self.image_list_filepath):
            self.log.error(
                "Path given for image list does not refer to a file")
            return False
        if not self.output_tracks_filepath:
            self.log.error("No output tracks file privided")
            return False
        if self.mask_list_filepath and not os.path.isfile(
                self.mask_list_filepath):
            self.log.error("Specified a mask list filepath, but path did not "
                           "refer to an existing file.")
            return False

        return (
            # Algorithms should check out valid
            self.algo_convert_img.check_config(
                self.algo_convert_img.get_config()) and
            self.algo_image_io.check_config(self.algo_image_io.get_config())
            and self.algo_track_features.check_config(
                self.algo_track_features.get_config()))

    def track_images(self):
        # Create list of input filepaths
        self.log.info("Reading input image list file...")
        with open(self.image_list_filepath, 'r') as image_list_file:
            input_filepaths = \
                [line.strip() for line in image_list_file.readlines()]

        # Create a list of mask images if we were given a list file
        mask_filepaths = None
        if self.mask_list_filepath:
            self.log.info("Reading mask image list file...")
            with open(self.mask_list_filepath) as mask_list_file:
                mask_filepaths = \
                    [line.strip() for line in mask_list_file.readlines()]

            if len(input_filepaths) != len(mask_filepaths):
                self.log.error("Input and Mask image lists were not congruent "
                               "in size.")
                return False

        # Check that the output tracks file is open-able and that the containing
        # directory exists.
        if not os.path.isdir(os.path.dirname(self.output_tracks_filepath)):
            self.log.info(
                "Creating containing directory for output tracks "
                "file: %s", os.path.dirname(self.output_tracks_filepath))
            os.mkdir(os.path.dirname(self.output_tracks_filepath))
        self.log.info("Testing that output tracks file is open-able...")
        test_f = open(self.output_tracks_filepath, 'w')
        test_f.close()

        tracks = TrackSet()
        for frame_num in xrange(len(input_filepaths)):
            input_img = self.algo_convert_img.convert(
                self.algo_image_io.load(input_filepaths[frame_num]))
            mask_img = None
            if mask_filepaths:
                mask_img = self.algo_convert_img.convert(
                    self.algo_image_io.load(mask_filepaths[frame_num]))
            self.log.info("Processing frame %d...", frame_num)
            tracks = self.algo_track_features.track(tracks, frame_num,
                                                    input_img, mask_img)

        self.log.info("Frame processing complete, writing out track set...")
        tracks.write_tracks_file(self.output_tracks_filepath)
Esempio n. 25
0
 def test_get_conf(self):
     ci = ConvertImage('ci')
     c = ci.get_config()
     nt.assert_list_equal(c.available_keys(), ['ci:type'])
     nt.assert_true(c.has_value('ci:type'))
     nt.assert_equal(c.get_value('ci:type'), '')
Esempio n. 26
0
 def test_create(self):
     ci = ConvertImage.create('ci', 'bypass')
     nt.assert_equal(ci.impl_name(), 'bypass')
Esempio n. 27
0
 def test_new(self):
     ci = ConvertImage('ci')
     nt.assert_false(ci)
     nt.assert_false(ci.c_pointer)
Esempio n. 28
0
 def test_set_conf(self):
     ci = ConvertImage('ci')
     nt.assert_false(ci)
     nt.assert_is_none(ci.impl_name())
Esempio n. 29
0
 def test_registered_names(self):
     nt.assert_in('bypass', ConvertImage.registered_names())
Esempio n. 30
0
 def test_impl_name(self):
     ci_empty = ConvertImage('ci')
     nt.assert_is_none(ci_empty.impl_name())
Esempio n. 31
0
 def test_impl_name(self):
     ci_empty = ConvertImage('ci')
     nt.assert_is_none(ci_empty.impl_name())
Esempio n. 32
0
 def test_typename(self):
     ci = ConvertImage('ci')
     nt.assert_equal(ci.type_name(), "convert_image")
Esempio n. 33
0
 def test_registered_names(self):
     nt.assert_in('bypass', ConvertImage.registered_names())
Esempio n. 34
0
 def test_clone_empty(self):
     ci_empty = ConvertImage('ci')
     ci_empty2 = ci_empty.clone()
     nt.assert_false(ci_empty)
     nt.assert_false(ci_empty2)
Esempio n. 35
0
 def test_from_c_ptr_null(self):
     ci = ConvertImage.from_c_pointer(ConvertImage.C_TYPE_PTR(), name='ci')
     nt.assert_false(ci.c_pointer)
Esempio n. 36
0
 def test_get_conf(self):
     ci = ConvertImage('ci')
     c = ci.get_config()
     nt.assert_list_equal(c.available_keys(), ['ci:type'])
     nt.assert_true(c.has_value('ci:type'))
     nt.assert_equal(c.get_value('ci:type'), '')
Esempio n. 37
0
 def test_from_c_ptr_copy(self):
     ci = ConvertImage('ci')
     ci_new = ConvertImage.from_c_pointer(ci.c_pointer, ci)
     nt.assert_is(ci.c_pointer, ci_new.c_pointer)
     nt.assert_equal(ci_new.name, ci.name)
Esempio n. 38
0
 def test_set_conf(self):
     ci = ConvertImage('ci')
     nt.assert_false(ci)
     nt.assert_is_none(ci.impl_name())
Esempio n. 39
0
 def test_create(self):
     ci = ConvertImage.create('ci', 'bypass')
     nt.assert_equal(ci.impl_name(), 'bypass')
Esempio n. 40
0
 def test_from_c_ptr_copy(self):
     ci = ConvertImage('ci')
     ci_new = ConvertImage.from_c_pointer(ci.c_pointer, ci)
     nt.assert_is(ci.c_pointer, ci_new.c_pointer)
     nt.assert_equal(ci_new.name, ci.name)
Esempio n. 41
0
 def test_typename(self):
     ci = ConvertImage('ci')
     nt.assert_equal(ci.type_name(), "convert_image")
Esempio n. 42
0
 def test_name(self):
     name = 'algo_name'
     ci = ConvertImage(name)
     nt.assert_equal(ci.name, name)
Esempio n. 43
0
 def test_impl_name(self):
     ci_empty = ConvertImage('ci')
     nt.assert_is_none(ci_empty.impl_name())
     ci_bypass = ConvertImage.create('ci', 'bypass')
     nt.assert_equal(ci_bypass.impl_name(), 'bypass')
Esempio n. 44
0
class TrackFeaturesTool (object):

    @property
    def log(self):
        return logging.getLogger("TrackFeaturesTool")

    def __init__(self):
        apm.register_plugins()

        # Algorithms
        self.algo_convert_img = ConvertImage("convert_image")
        self.algo_image_io = ImageIo("image_reader")
        self.algo_track_features = TrackFeatures("feature_tracker")

        # Other tool variables
        self.image_list_filepath = None
        self.mask_list_filepath = None
        self.invert_masks = False
        self.expect_multichannel_masks = False
        self.output_tracks_filepath = None

    def get_configuration(self):
        """
        :return: the current tool configuration
        :rtype: ConfigBlock
        """
        c = ConfigBlock("track_features")
        c.set_value("image_list_file",
                    self.image_list_filepath or "",
                    "Path to an input file containing new-line separated paths "
                    "to sequential image files")
        c.set_value("mask_list_file",
                    self.mask_list_filepath or "",
                    "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",
                    str(self.invert_masks).lower(),
                    "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",
                    str(self.expect_multichannel_masks).lower(),
                    "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",
                    self.output_tracks_filepath or "",
                    "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",
        #             self.output_homography_filepath or "",
        #             "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.")

        self.algo_convert_img.get_config(c)
        self.algo_image_io.get_config(c)
        self.algo_track_features.get_config(c)

        return c

    def set_configuration(self, config):
        """
        Set the tool configuration
        :param config: The configuration to set
        :type config: ConfigBlock
        """
        self.algo_convert_img.set_config(config)
        self.algo_image_io.set_config(config)
        self.algo_track_features.set_config(config)

        abspath = lambda p: os.path.abspath(os.path.expanduser(p))

        self.image_list_filepath = config.get_value('image_list_file',
                                                    self.image_list_filepath)
        if self.image_list_filepath:
            self.image_list_filepath = abspath(self.image_list_filepath)
        self.mask_list_filepath = config.get_value('mask_list_file',
                                                   self.mask_list_filepath)
        if self.mask_list_filepath:
            self.mask_list_filepath = abspath(self.mask_list_filepath)
        self.invert_masks = config.get_value_bool('invert_masks', self.invert_masks)
        self.expect_multichannel_masks = \
            config.get_value_bool('expect_multichannel_masks',
                            self.expect_multichannel_masks)
        self.output_tracks_filepath = \
            config.get_value('output_tracks_file', self.output_tracks_filepath)
        if self.output_tracks_filepath:
            self.output_tracks_filepath = abspath(self.output_tracks_filepath)

    def validate_configuration(self):
        """
        Check the current configuration for validity
        :return: True if valid, false if not.
        :type: bool
        """
        if not self.image_list_filepath:
            self.log.error("No image list file provided")
            return False
        if not os.path.isfile(self.image_list_filepath):
            self.log.error("Path given for image list does not refer to a file")
            return False
        if not self.output_tracks_filepath:
            self.log.error("No output tracks file privided")
            return False
        if self.mask_list_filepath and not os.path.isfile(self.mask_list_filepath):
            self.log.error("Specified a mask list filepath, but path did not "
                           "refer to an existing file.")
            return False

        return (
            # Algorithms should check out valid
            self.algo_convert_img.check_config(self.algo_convert_img.get_config())
            and self.algo_image_io.check_config(self.algo_image_io.get_config())
            and self.algo_track_features.check_config(self.algo_track_features.get_config())
        )

    def track_images(self):
        # Create list of input filepaths
        self.log.info("Reading input image list file...")
        with open(self.image_list_filepath, 'r') as image_list_file:
            input_filepaths = \
                [line.strip() for line in image_list_file.readlines()]

        # Create a list of mask images if we were given a list file
        mask_filepaths = None
        if self.mask_list_filepath:
            self.log.info("Reading mask image list file...")
            with open(self.mask_list_filepath) as mask_list_file:
                mask_filepaths = \
                    [line.strip() for line in mask_list_file.readlines()]

            if len(input_filepaths) != len(mask_filepaths):
                self.log.error("Input and Mask image lists were not congruent "
                               "in size.")
                return False

        # Check that the output tracks file is open-able and that the containing
        # directory exists.
        if not os.path.isdir(os.path.dirname(self.output_tracks_filepath)):
            self.log.info("Creating containing directory for output tracks "
                          "file: %s",
                          os.path.dirname(self.output_tracks_filepath))
            os.mkdir(os.path.dirname(self.output_tracks_filepath))
        self.log.info("Testing that output tracks file is open-able...")
        test_f = open(self.output_tracks_filepath, 'w')
        test_f.close()

        tracks = TrackSet()
        for frame_num in xrange(len(input_filepaths)):
            input_img = self.algo_convert_img.convert(
                self.algo_image_io.load(input_filepaths[frame_num])
            )
            mask_img = None
            if mask_filepaths:
                mask_img = self.algo_convert_img.convert(
                    self.algo_image_io.load(mask_filepaths[frame_num])
                )
            self.log.info("Processing frame %d...", frame_num)
            tracks = self.algo_track_features.track(tracks, frame_num,
                                                    input_img, mask_img)

        self.log.info("Frame processing complete, writing out track set...")
        tracks.write_tracks_file(self.output_tracks_filepath)