From 769aeb478579d73db92976f7fe339ccd5ebb3f25 Mon Sep 17 00:00:00 2001
From: Amir Mohammadi <183.amir@gmail.com>
Date: Mon, 3 Apr 2017 14:31:11 +0200
Subject: [PATCH] Add support for annotations

---
 bob/pad/base/database/database.py  | 16 ++++++++++++++--
 bob/pad/base/tools/FileSelector.py |  7 +++++++
 bob/pad/base/tools/preprocessor.py |  9 ++++++++-
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/bob/pad/base/database/database.py b/bob/pad/base/database/database.py
index 5be494f..ae31988 100644
--- a/bob/pad/base/database/database.py
+++ b/bob/pad/base/database/database.py
@@ -85,12 +85,24 @@ class PadDatabase(BioDatabase):
         """
         return []
 
+    @abc.abstractmethod
     def annotations(self, file):
         """
-        Annotations are not supported by PAD interface
+        Returns the annotations for the given File object, if available.
+        You need to override this method in your high-level implementation.
+        If your database does not have annotations, it should return ``None``.
+
+        **Parameters:**
+
+        file : :py:class:`bob.pad.base.database.PadFile`
+          The file for which annotations should be returned.
 
+        **Returns:**
+
+        annots : dict or None
+          The annotations for the file, if available.
         """
-        return None
+        raise NotImplementedError("This function must be implemented in your derived class.")
 
     @abc.abstractmethod
     def objects(self, groups=None, protocol=None, purposes=None, model_ids=None, **kwargs):
diff --git a/bob/pad/base/tools/FileSelector.py b/bob/pad/base/tools/FileSelector.py
index 79401f6..4059c6a 100644
--- a/bob/pad/base/tools/FileSelector.py
+++ b/bob/pad/base/tools/FileSelector.py
@@ -147,3 +147,10 @@ class FileSelector(object):
         no_norm_dir = self.score_directories[0]
         return os.path.join(no_norm_dir, "scores-" + group + "-" + obj_type) + self.compressed_extension
 
+    def annotation_list(self, groups=None):
+        """Returns the list of annotations objects."""
+        return self.database.all_files(groups=groups)
+
+    def get_annotations(self, annotation_file):
+        """Returns the annotations of the given file."""
+        return self.database.annotations(annotation_file)
diff --git a/bob/pad/base/tools/preprocessor.py b/bob/pad/base/tools/preprocessor.py
index 9ce6ee6..4df9476 100644
--- a/bob/pad/base/tools/preprocessor.py
+++ b/bob/pad/base/tools/preprocessor.py
@@ -46,6 +46,9 @@ def preprocess(preprocessor, groups=None, indices=None, allow_missing_files=Fals
     data_files, original_directory, original_extension = fs.original_data_list_files(groups=groups)
     preprocessed_data_files = fs.preprocessed_data_list(groups=groups)
 
+    # read annotation files
+    annotation_list = fs.annotation_list(groups=groups)
+
     # select a subset of keys to iterate
     if indices is not None:
         index_range = range(indices[0], indices[1])
@@ -56,6 +59,7 @@ def preprocess(preprocessor, groups=None, indices=None, allow_missing_files=Fals
     logger.info("- Preprocessing: processing %d data files from directory '%s' to directory '%s'", len(index_range),
                 fs.directories['original'], fs.directories['preprocessed'])
 
+
     # iterate over the selected files
     for i in index_range:
         preprocessed_data_file = str(preprocessed_data_files[i])
@@ -69,8 +73,11 @@ def preprocess(preprocessor, groups=None, indices=None, allow_missing_files=Fals
             # create output directory before reading the data file (is sometimes required, when relative directories are specified, especially, including a .. somewhere)
             bob.io.base.create_directories_safe(os.path.dirname(preprocessed_data_file))
 
+            # get the annotations; might be None
+            annotations = fs.get_annotations(annotation_list[i])
+
             # call the preprocessor
-            preprocessed_data = preprocessor(data, None)
+            preprocessed_data = preprocessor(data, annotations)
             if preprocessed_data is None:
                 logger.error("Preprocessing of file '%s' was not successful", file_name)
                 continue
-- 
GitLab