Coverage for src/bob/bio/base/database/database.py: 41%
174 statements
« prev ^ index » next coverage.py v7.6.5, created at 2024-11-14 21:41 +0100
« prev ^ index » next coverage.py v7.6.5, created at 2024-11-14 21:41 +0100
1#!/usr/bin/env python
2# vim: set fileencoding=utf-8 :
4import abc
5import os
7from .file import BioFile
8from .legacy import FileDatabase as LegacyFileDatabase
11class BioDatabase(LegacyFileDatabase, metaclass=abc.ABCMeta):
12 """This class represents the basic API for database access.
13 Please use this class as a base class for your database access classes.
14 Do not forget to call the constructor of this base class in your derived class.
16 **Parameters:**
18 name : str
19 A unique name for the database.
21 all_files_options : dict
22 Dictionary of options passed to the :py:meth:`bob.bio.base.database.BioDatabase.objects` database query when retrieving all data.
24 extractor_training_options : dict
25 Dictionary of options passed to the :py:meth:`bob.bio.base.database.BioDatabase.objects` database query used to retrieve the files for the extractor training.
27 projector_training_options : dict
28 Dictionary of options passed to the :py:meth:`bob.bio.base.database.BioDatabase.objects` database query used to retrieve the files for the projector training.
30 enroller_training_options : dict
31 Dictionary of options passed to the :py:meth:`bob.bio.base.database.BioDatabase.objects` database query used to retrieve the files for the enroller training.
33 check_original_files_for_existence : bool
34 Enables to test for the original data files when querying the database.
36 original_directory : str
37 The directory where the original data of the database are stored.
39 original_extension : str
40 The file name extension of the original data.
42 annotation_directory : str
43 The directory where the image annotations of the database are stored, if any.
45 annotation_extension : str
46 The file name extension of the annotation files.
48 annotation_type : str
49 The type of the annotation file to read, only json works.
51 protocol : str or ``None``
52 The name of the protocol that defines the default experimental setup for this database.
54 training_depends_on_protocol : bool
55 Specifies, if the training set used for training the extractor and the projector depend on the protocol.
56 This flag is used to avoid re-computation of data when running on the different protocols of the same database.
58 models_depend_on_protocol : bool
59 Specifies, if the models depend on the protocol.
60 This flag is used to avoid re-computation of models when running on the different protocols of the same database.
62 kwargs : ``key=value`` pairs
63 The arguments of the `Database` base class constructor.
65 """
67 # tell test runners (such as nose and pytest) that this class is not a test class
68 ___test___ = False
70 def __init__(
71 self,
72 name,
73 all_files_options={}, # additional options for the database query that can be used to extract all files
74 extractor_training_options={},
75 # additional options for the database query that can be used to extract the training files for the extractor training
76 projector_training_options={},
77 # additional options for the database query that can be used to extract the training files for the extractor training
78 enroller_training_options={},
79 # additional options for the database query that can be used to extract the training files for the extractor training
80 check_original_files_for_existence=False,
81 original_directory=None,
82 original_extension=None,
83 annotation_directory=None,
84 annotation_extension=None,
85 annotation_type=None,
86 protocol="Default",
87 training_depends_on_protocol=False,
88 models_depend_on_protocol=False,
89 **kwargs,
90 ):
91 assert isinstance(name, str)
93 super(BioDatabase, self).__init__(
94 original_directory=original_directory,
95 original_extension=original_extension,
96 **kwargs,
97 )
99 self.name = name
101 self.all_files_options = all_files_options
102 self.extractor_training_options = extractor_training_options
103 self.projector_training_options = projector_training_options
104 self.enroller_training_options = enroller_training_options
105 self.check_existence = check_original_files_for_existence
107 self._kwargs = {}
109 self.annotation_directory = annotation_directory
110 self.annotation_extension = annotation_extension or ".json"
111 self.annotation_type = annotation_type or "json"
112 self.protocol = protocol
113 self.training_depends_on_protocol = training_depends_on_protocol
114 self.models_depend_on_protocol = models_depend_on_protocol
115 self.models_depend_on_protocol = models_depend_on_protocol
117 # try if the implemented model_ids_with_protocol() and objects() function have at least the required interface
118 try:
119 # create a value that is very unlikely a valid value for anything
120 test_value = "#6T7+§X"
121 # test if the parameters of the functions apply
122 self.model_ids_with_protocol(groups=test_value, protocol=test_value)
123 self.objects(
124 groups=test_value,
125 protocol=test_value,
126 purposes=test_value,
127 model_ids=(test_value,),
128 )
129 self.annotations(file=BioFile(test_value, test_value, test_value))
130 except TypeError as e:
131 # type error indicates that the given parameters are not valid.
132 raise NotImplementedError(
133 str(e)
134 + "\nPlease implement:\n - the model_ids_with_protocol(...) function with at least the "
135 "arguments 'groups' and 'protocol'\n - the objects(...) function with at least the "
136 "arguments 'groups', 'protocol', 'purposes' and 'model_ids'\n - the annotations() "
137 "function with at least the arguments 'file_id'."
138 )
139 except Exception:
140 # any other error is fine at this stage.
141 pass
143 def __str__(self):
144 """__str__() -> info
146 This function returns all parameters of this class.
148 **Returns:**
150 info : str
151 A string containing the full information of all parameters of this class.
152 """
153 params = (
154 "name=%s, protocol=%s, original_directory=%s, original_extension=%s"
155 % (
156 self.name,
157 self.protocol,
158 self.original_directory,
159 self.original_extension,
160 )
161 )
162 params += ", ".join(
163 ["%s=%s" % (key, value) for key, value in self._kwargs.items()]
164 )
165 params += ", original_directory=%s, original_extension=%s" % (
166 self.original_directory,
167 self.original_extension,
168 )
169 if self.all_files_options:
170 params += ", all_files_options=%s" % self.all_files_options
171 if self.extractor_training_options:
172 params += (
173 ", extractor_training_options=%s"
174 % self.extractor_training_options
175 )
176 if self.projector_training_options:
177 params += (
178 ", projector_training_options=%s"
179 % self.projector_training_options
180 )
181 if self.enroller_training_options:
182 params += (
183 ", enroller_training_options=%s"
184 % self.enroller_training_options
185 )
187 return "%s(%s)" % (str(self.__class__), params)
189 def replace_directories(self, replacements=None):
190 """This helper function replaces the ``original_directory`` and the ``annotation_directory`` of the database with the directories read from the given replacement file.
192 This function is provided for convenience, so that the database configuration files do not need to be modified.
193 Instead, this function uses the given dictionary of replacements to change the original directory and the original extension (if given).
195 The given ``replacements`` can be of type ``dict``, including all replacements, or a file name (as a ``str``), in which case the file is read.
196 The structure of the file should be:
198 .. code-block:: text
200 # Comments starting with # and empty lines are ignored
202 [YOUR_..._DATA_DIRECTORY] = /path/to/your/data
203 [YOUR_..._ANNOTATION_DIRECTORY] = /path/to/your/annotations
205 If no annotation files are available (e.g. when they are stored inside the ``database``), the annotation directory can be left out.
207 **Parameters:**
209 replacements : dict or str
210 A dictionary with replacements, or a name of a file to read the dictionary from.
211 If the file name does not exist, no directories are replaced.
212 """
213 if replacements is None:
214 return
215 if isinstance(replacements, str):
216 if not os.path.exists(replacements):
217 return
218 # Open the database replacement file and reads its content
219 with open(replacements) as f:
220 replacements = {}
221 for line in f:
222 if line.strip() and not line.startswith("#"):
223 splits = line.split("=")
224 assert len(splits) == 2
225 replacements[splits[0].strip()] = splits[1].strip()
227 assert isinstance(replacements, dict)
229 if self.original_directory in replacements:
230 self.original_directory = replacements[self.original_directory]
232 try:
233 if self.annotation_directory in replacements:
234 self.annotation_directory = replacements[
235 self.annotation_directory
236 ]
237 except AttributeError:
238 pass
240 ###########################################################################
241 # Helper functions that you might want to use in derived classes
242 ###########################################################################
243 def uses_probe_file_sets(self, protocol=None):
244 """Defines if, for the current protocol, the database uses several probe files to generate a score.
245 Returns True if the given protocol specifies file sets for probes, instead of a single probe file.
246 In this default implementation, False is returned, throughout.
247 If you need different behavior, please overload this function in your derived class.
248 """
249 return False
251 def arrange_by_client(self, files):
252 """arrange_by_client(files) -> files_by_client
254 Arranges the given list of files by client id.
255 This function returns a list of lists of File's.
257 **Parameters:**
259 files : :py:class:`bob.bio.base.database.BioFile`
260 A list of files that should be split up by `BioFile.client_id`.
262 **Returns:**
264 files_by_client : [[:py:class:`bob.bio.base.database.BioFile`]]
265 The list of lists of files, where each sub-list groups the files with the same `BioFile.client_id`
266 """
267 client_files = {}
268 for file in files:
269 if file.client_id not in client_files:
270 client_files[file.client_id] = []
271 client_files[file.client_id].append(file)
273 files_by_clients = []
274 for client in sorted(client_files.keys()):
275 files_by_clients.append(client_files[client])
276 return files_by_clients
278 def file_names(self, files, directory, extension):
279 """file_names(files, directory, extension) -> paths
281 Returns the full path of the given File objects.
283 **Parameters:**
285 files : [:py:class:`bob.bio.base.database.BioFile`]
286 The list of file object to retrieve the file names for.
288 directory : str
289 The base directory, where the files can be found.
291 extension : str
292 The file name extension to add to all files.
294 **Returns:**
296 paths : [str] or [[str]]
297 The paths extracted for the files, in the same order.
298 If this database provides file sets, a list of lists of file names is returned, one sub-list for each file set.
299 """
300 # return the paths of the files
301 if self.uses_probe_file_sets() and files and hasattr(files[0], "files"):
302 # List of Filesets: do not remove duplicates
303 return [
304 [f.make_path(directory, extension) for f in file_set.files]
305 for file_set in files
306 ]
307 else:
308 # List of files, do not remove duplicates
309 return [f.make_path(directory, extension) for f in files]
311 #################################################################
312 # Methods to be overwritten by derived classes
313 #################################################################
314 @abc.abstractmethod
315 def model_ids_with_protocol(self, groups=None, protocol=None, **kwargs):
316 """model_ids_with_protocol(groups = None, protocol = None, **kwargs) -> ids
318 Returns a list of model ids for the given groups and given protocol.
320 **Parameters:**
322 groups : one or more of ``('world', 'dev', 'eval')``
323 The groups to get the model ids for.
325 protocol: a protocol name
327 **Returns:**
329 ids : [int] or [str]
330 The list of (unique) model ids for the given groups.
331 """
332 raise NotImplementedError(
333 "Please implement this function in derived classes"
334 )
336 def groups(self, protocol=None):
337 """
338 Returns the names of all registered groups in the database
340 Keyword parameters:
342 protocol: str
343 The protocol for which the groups should be retrieved.
344 If you do not have protocols defined, just ignore this field.
345 """
346 raise NotImplementedError(
347 "This function must be implemented in your derived class."
348 )
350 @abc.abstractmethod
351 def objects(
352 self,
353 groups=None,
354 protocol=None,
355 purposes=None,
356 model_ids=None,
357 **kwargs,
358 ):
359 """This function returns a list of :py:class:`bob.bio.base.database.BioFile` objects or the list
360 of objects which inherit from this class. Returned files fulfill the given restrictions.
362 Keyword parameters:
364 groups : str or [str]
365 The groups of which the clients should be returned.
366 Usually, groups are one or more elements of ('world', 'dev', 'eval')
368 protocol
369 The protocol for which the clients should be retrieved.
370 The protocol is dependent on your database.
371 If you do not have protocols defined, just ignore this field.
373 purposes : str or [str]
374 The purposes for which File objects should be retrieved.
375 Usually, purposes are one of ('enroll', 'probe').
377 model_ids : [various type]
378 The model ids for which the File objects should be retrieved.
379 What defines a 'model id' is dependent on the database.
380 In cases, where there is only one model per client, model ids and client ids are identical.
381 In cases, where there is one model per file, model ids and file ids are identical.
382 But, there might also be other cases.
383 """
384 raise NotImplementedError(
385 "This function must be implemented in your derived class."
386 )
388 def annotations(self, file):
389 """
390 Returns the annotations for the given File object, if available.
391 You need to override this method in your high-level implementation.
392 If your database does not have annotations, it should return ``None``.
394 **Parameters:**
396 file : :py:class:`bob.bio.base.database.BioFile`
397 The file for which annotations should be returned.
399 **Returns:**
401 annots : dict or None
402 The annotations for the file, if available.
403 """
404 raise NotImplementedError(
405 "This function must be implemented in your derived class."
406 )
408 #################################################################
409 # Methods to provide common functionality
410 #################################################################
412 def model_ids(self, groups="dev"):
413 """model_ids(group = 'dev') -> ids
415 Returns a list of model ids for the given group, respecting the current protocol.
417 **Parameters:**
419 group : one of ``('dev', 'eval')``
420 The group to get the model ids for.
422 **Returns:**
424 ids : [int] or [str]
425 The list of (unique) model ids for models of the given group.
426 """
427 return sorted(
428 self.model_ids_with_protocol(groups=groups, protocol=self.protocol)
429 )
431 def all_files(self, groups=None, **kwargs):
432 """all_files(groups=None) -> files
434 Returns all files of the database, respecting the current protocol.
435 The files can be limited using the ``all_files_options`` in the constructor.
437 **Parameters:**
439 groups : some of ``('world', 'dev', 'eval')`` or ``None``
440 The groups to get the data for.
441 If ``None``, data for all groups is returned.
443 kwargs: ignored
445 **Returns:**
447 files : [:py:class:`bob.bio.base.database.BioFile`]
448 The sorted and unique list of all files of the database.
449 """
450 return self.sort(
451 self.objects(
452 protocol=self.protocol, groups=groups, **self.all_files_options
453 )
454 )
456 def training_files(self, step=None, arrange_by_client=False):
457 """training_files(step = None, arrange_by_client = False) -> files
459 Returns all training files for the given step, and arranges them by client, if desired, respecting the current protocol.
460 The files for the steps can be limited using the ``..._training_options`` defined in the constructor.
462 **Parameters:**
464 step : one of ``('train_extractor', 'train_projector', 'train_enroller')`` or ``None``
465 The step for which the training data should be returned.
467 arrange_by_client : bool
468 Should the training files be arranged by client?
469 If set to ``True``, training files will be returned in [[:py:class:`bob.bio.base.database.BioFile`]], where each sub-list contains the files of a single client.
470 Otherwise, all files will be stored in a simple [:py:class:`bob.bio.base.database.BioFile`].
472 **Returns:**
474 files : [:py:class:`bob.bio.base.database.BioFile`] or [[:py:class:`bob.bio.base.database.BioFile`]]
475 The (arranged) list of files used for the training of the given step.
476 """
477 if step is None:
478 training_options = self.all_files_options
479 elif step == "train_extractor":
480 training_options = self.extractor_training_options
481 elif step == "train_projector":
482 training_options = self.projector_training_options
483 elif step == "train_enroller":
484 training_options = self.enroller_training_options
485 else:
486 raise ValueError(
487 "The given step '%s' must be one of ('train_extractor', 'train_projector', 'train_enroller')"
488 % step
489 )
491 files = self.sort(
492 self.objects(
493 protocol=self.protocol, groups="world", **training_options
494 )
495 )
496 if arrange_by_client:
497 return self.arrange_by_client(files)
498 else:
499 return files
501 def test_files(self, groups=["dev"]):
502 """test_files(groups = ['dev']) -> files
504 Returns all test files (i.e., files used for enrollment and probing) for the given groups, respecting the current protocol.
505 The files for the steps can be limited using the ``all_files_options`` defined in the constructor.
507 **Parameters:**
509 groups : some of ``('dev', 'eval')``
510 The groups to get the data for.
512 **Returns:**
514 files : [:py:class:`bob.bio.base.database.BioFile`]
515 The sorted and unique list of test files of the database.
516 """
517 return self.sort(
518 self.objects(
519 protocol=self.protocol, groups=groups, **self.all_files_options
520 )
521 )
523 def enroll_files(self, model_id=None, group="dev"):
524 """enroll_files(model_id, group = 'dev') -> files
526 Returns a list of File objects that should be used to enroll the model with the given model id from the given group, respecting the current protocol.
527 If the model_id is None (the default), enrollment files for all models are returned.
529 **Parameters:**
531 model_id : int or str
532 A unique ID that identifies the model.
534 group : one of ``('dev', 'eval')``
535 The group to get the enrollment files for.
537 **Returns:**
539 files : [:py:class:`bob.bio.base.database.BioFile`]
540 The list of files used for to enroll the model with the given model id.
541 """
542 if model_id:
543 return self.sort(
544 self.objects(
545 protocol=self.protocol,
546 groups=group,
547 model_ids=(model_id,),
548 purposes="enroll",
549 **self.all_files_options,
550 )
551 )
552 else:
553 return self.sort(
554 self.objects(
555 protocol=self.protocol,
556 groups=group,
557 purposes="enroll",
558 **self.all_files_options,
559 )
560 )
562 def probe_files(self, model_id=None, group="dev"):
563 """probe_files(model_id = None, group = 'dev') -> files
565 Returns a list of probe File objects, respecting the current protocol.
566 If a ``model_id`` is specified, only the probe files that should be compared with the given model id are returned (for most databases, these are all probe files of the given group).
567 Otherwise, all probe files of the given group are returned.
569 **Parameters:**
571 model_id : int or str or ``None``
572 A unique ID that identifies the model.
574 group : one of ``('dev', 'eval')``
575 The group to get the enrollment files for.
577 **Returns:**
579 files : [:py:class:`bob.bio.base.database.BioFile`]
580 The list of files used for to probe the model with the given model id.
581 """
582 if model_id is not None:
583 files = self.objects(
584 protocol=self.protocol,
585 groups=group,
586 model_ids=(model_id,),
587 purposes="probe",
588 **self.all_files_options,
589 )
590 else:
591 files = self.objects(
592 protocol=self.protocol,
593 groups=group,
594 purposes="probe",
595 **self.all_files_options,
596 )
597 return self.sort(files)
599 def object_sets(
600 self,
601 groups=None,
602 protocol=None,
603 purposes=None,
604 model_ids=None,
605 **kwargs,
606 ):
607 """This function returns lists of FileSet objects, which fulfill the given restrictions.
609 Keyword parameters:
611 groups : str or [str]
612 The groups of which the clients should be returned.
613 Usually, groups are one or more elements of ('world', 'dev', 'eval')
615 protocol
616 The protocol for which the clients should be retrieved.
617 The protocol is dependent on your database.
618 If you do not have protocols defined, just ignore this field.
620 purposes : str or [str]
621 The purposes for which File objects should be retrieved.
622 Usually, purposes are one of ('enroll', 'probe').
624 model_ids : [various type]
625 The model ids for which the File objects should be retrieved.
626 What defines a 'model id' is dependent on the database.
627 In cases, where there is only one model per client, model ids and client ids are identical.
628 In cases, where there is one model per file, model ids and file ids are identical.
629 But, there might also be other cases.
630 """
631 raise NotImplementedError(
632 "This function must be implemented in your derived class."
633 )
635 def probe_file_sets(self, model_id=None, group="dev"):
636 """probe_file_sets(model_id = None, group = 'dev') -> files
638 Returns a list of probe FileSet objects, respecting the current protocol.
639 If a ``model_id`` is specified, only the probe files that should be compared with the given model id are returned (for most databases, these are all probe files of the given group).
640 Otherwise, all probe files of the given group are returned.
642 **Parameters:**
644 model_id : int or str or ``None``
645 A unique ID that identifies the model.
647 group : one of ``('dev', 'eval')``
648 The group to get the enrollment files for.
650 **Returns:**
652 files : [:py:class:`bob.bio.base.database.BioFileSet`] or something similar
653 The list of file sets used to probe the model with the given model id.
654 """
655 if model_id is not None:
656 file_sets = self.object_sets(
657 protocol=self.protocol,
658 groups=group,
659 model_ids=(model_id,),
660 purposes="probe",
661 **self.all_files_options,
662 )
663 else:
664 file_sets = self.object_sets(
665 protocol=self.protocol,
666 groups=group,
667 purposes="probe",
668 **self.all_files_options,
669 )
670 return self.sort(file_sets)
672 def client_id_from_model_id(self, model_id, group="dev"):
673 """Return the client id associated with the given model id.
674 In this base class implementation, it is assumed that only one model is enrolled for each client and, thus, client id and model id are identical.
675 All key word arguments are ignored.
676 Please override this function in derived class implementations to change this behavior.
677 """
678 return model_id
681class ZTBioDatabase(BioDatabase):
682 """This class defines another set of abstract functions that need to be implemented if your database provides the interface for computing scores used for ZT-normalization."""
684 def __init__(
685 self, name, z_probe_options={}, **kwargs
686 ): # Limit the z-probes
687 """**Construtctor Documentation**
689 This constructor tests if all implemented functions take the correct arguments.
690 All keyword parameters will be passed unaltered to the :py:class:`bob.bio.base.database.BioDatabase` constructor.
691 """
692 # call base class constructor
693 super(ZTBioDatabase, self).__init__(name, **kwargs)
695 self.z_probe_options = z_probe_options
697 # try if the implemented tmodel_ids_with_protocol(), tobjects() and zobjects() function have at least the required interface
698 try:
699 # create a value that is very unlikely a valid value for anything
700 test_value = "#F9S%3*Y"
701 # test if the parameters of the functions apply
702 self.tmodel_ids_with_protocol(
703 groups=test_value, protocol=test_value
704 )
705 self.tobjects(
706 groups=test_value, protocol=test_value, model_ids=test_value
707 )
708 self.zobjects(groups=test_value, protocol=test_value)
709 except TypeError as e:
710 # type error indicates that the given parameters are not valid.
711 raise NotImplementedError(
712 str(e)
713 + "\nPlease implement:\n - the tmodel_ids_with_protocol(...) function with at least the "
714 "arguments 'groups' and 'protocol'\n - the tobjects(...) function with at least the arguments "
715 "'groups', 'protocol' and 'model_ids'\n - the zobjects(...) function with at "
716 "least the arguments 'groups' and 'protocol'"
717 )
718 except Exception:
719 # any other error is fine at this stage.
720 pass
722 @abc.abstractmethod
723 def tobjects(self, groups=None, protocol=None, model_ids=None, **kwargs):
724 """This function returns the File objects of the T-Norm models of the given groups for the given protocol and the given model ids.
726 Keyword parameters:
728 groups : str or [str]
729 The groups of which the model ids should be returned.
730 Usually, groups are one or more elements of ('dev', 'eval')
732 protocol : str
733 The protocol for which the model ids should be retrieved.
734 The protocol is dependent on your database.
735 If you do not have protocols defined, just ignore this field.
737 model_ids : [various type]
738 The model ids for which the File objects should be retrieved.
739 What defines a 'model id' is dependent on the database.
740 In cases, where there is only one model per client, model ids and client ids are identical.
741 In cases, where there is one model per file, model ids and file ids are identical.
742 But, there might also be other cases.
743 """
744 raise NotImplementedError(
745 "This function must be implemented in your derived class."
746 )
748 @abc.abstractmethod
749 def zobjects(self, groups=None, protocol=None, **kwargs):
750 """This function returns the File objects of the Z-Norm impostor files of the given groups for the given protocol.
752 Keyword parameters:
754 groups : str or [str]
755 The groups of which the model ids should be returned.
756 Usually, groups are one or more elements of ('dev', 'eval')
758 protocol : str
759 The protocol for which the model ids should be retrieved.
760 The protocol is dependent on your database.
761 If you do not have protocols defined, just ignore this field.
762 """
763 raise NotImplementedError(
764 "This function must be implemented in your derived class."
765 )
767 def all_files(self, groups=["dev"], add_zt_files=True):
768 """all_files(groups=None) -> files
770 Returns all files of the database, including those for ZT norm, respecting the current protocol.
771 The files can be limited using the ``all_files_options`` and the the ``z_probe_options`` in the constructor.
773 **Parameters:**
775 groups : some of ``('world', 'dev', 'eval')`` or ``None``
776 The groups to get the data for.
777 If ``None``, data for all groups is returned.
779 add_zt_files: bool
780 If set (the default), files for ZT score normalization are added.
782 **Returns:**
784 files : [:py:class:`bob.bio.base.database.BioFile`]
785 The sorted and unique list of all files of the database.
786 """
787 files = self.objects(
788 protocol=self.protocol, groups=groups, **self.all_files_options
789 )
791 # add all files that belong to the ZT-norm
792 if add_zt_files and groups:
793 for group in groups:
794 if group == "world":
795 continue
796 files += self.tobjects(
797 protocol=self.protocol, groups=group, model_ids=None
798 )
799 files += self.zobjects(
800 protocol=self.protocol, groups=group, **self.z_probe_options
801 )
802 elif add_zt_files:
803 files += self.tobjects(
804 protocol=self.protocol, groups=groups, model_ids=None
805 )
806 files += self.zobjects(
807 protocol=self.protocol, groups=groups, **self.z_probe_options
808 )
809 return self.sort(files)
811 @abc.abstractmethod
812 def tmodel_ids_with_protocol(self, protocol=None, groups=None, **kwargs):
813 """This function returns the ids of the T-Norm models of the given groups for the given protocol.
815 Keyword parameters:
817 groups : str or [str]
818 The groups of which the model ids should be returned.
819 Usually, groups are one or more elements of ('dev', 'eval')
821 protocol : str
822 The protocol for which the model ids should be retrieved.
823 The protocol is dependent on your database.
824 If you do not have protocols defined, just ignore this field.
825 """
826 raise NotImplementedError(
827 "This function must be implemented in your derived class."
828 )
830 def t_model_ids(self, groups="dev"):
831 """t_model_ids(group = 'dev') -> ids
833 Returns a list of model ids of T-Norm models for the given group, respecting the current protocol.
835 **Parameters:**
837 group : one of ``('dev', 'eval')``
838 The group to get the model ids for.
840 **Returns:**
842 ids : [int] or [str]
843 The list of (unique) model ids for T-Norm models of the given group.
844 """
845 return sorted(
846 self.tmodel_ids_with_protocol(protocol=self.protocol, groups=groups)
847 )
849 def t_enroll_files(self, t_model_id, group="dev"):
850 """t_enroll_files(t_model_id, group = 'dev') -> files
852 Returns a list of File objects that should be used to enroll the T-Norm model with the given model id from the given group, respecting the current protocol.
854 **Parameters:**
856 t_model_id : int or str
857 A unique ID that identifies the model.
859 group : one of ``('dev', 'eval')``
860 The group to get the enrollment files for.
862 **Returns:**
864 files : [:py:class:`bob.bio.base.database.BioFile`]
865 The sorted list of files used for to enroll the model with the given model id.
866 """
867 return self.sort(
868 self.tobjects(
869 protocol=self.protocol, groups=group, model_ids=(t_model_id,)
870 )
871 )
873 def z_probe_files(self, group="dev"):
874 """z_probe_files(group = 'dev') -> files
876 Returns a list of probe files used to compute the Z-Norm, respecting the current protocol.
877 The Z-probe files can be limited using the ``z_probe_options`` in the query to :py:meth:`bob.bio.base.database.ZTBioDatabase.z_probe_files`
879 **Parameters:**
881 group : one of ``('dev', 'eval')``
882 The group to get the Z-norm probe files for.
884 **Returns:**
886 files : [:py:class:`bob.bio.base.database.BioFile`]
887 The unique list of files used to compute the Z-norm.
888 """
889 return self.sort(
890 self.zobjects(
891 protocol=self.protocol, groups=group, **self.z_probe_options
892 )
893 )
895 def z_probe_file_sets(self, group="dev"):
896 """z_probe_file_sets(group = 'dev') -> files
898 Returns a list of probe FileSet objects used to compute the Z-Norm.
899 This function needs to be implemented in derived class implementations.
901 **Parameters:**
903 group : one of ``('dev', 'eval')``
904 The group to get the Z-norm probe files for.
906 **Returns:**
908 files : [:py:class:`bob.bio.base.database.BioFileSet`]
909 The unique list of file sets used to compute the Z-norm.
910 """
911 raise NotImplementedError(
912 "Please implement this function in derived classes"
913 )
915 def client_id_from_t_model_id(self, t_model_id, group="dev"):
916 """client_id_from_t_model_id(t_model_id, group = 'dev') -> client_id
917 Returns the client id for the given T-Norm model id.
918 In this base class implementation, we just use the :py:meth:`BioDatabase.client_id_from_model_id` function.
919 Overload this function if you need another behavior.
921 **Parameters:**
923 t_model_id : int or str
924 A unique ID that identifies the T-Norm model.
925 group : one of ``('dev', 'eval')``
926 The group to get the client ids for.
928 **Returns:**
930 client_id : [int] or [str]
931 A unique ID that identifies the client, to which the T-Norm model belongs.
932 """
933 return self.client_id_from_model_id(t_model_id, group)