diff --git a/advanced/databases/replay/5.json b/advanced/databases/replay/5.json new file mode 100644 index 0000000000000000000000000000000000000000..f9a77e25e622ded247d227832475ca10b8be886a --- /dev/null +++ b/advanced/databases/replay/5.json @@ -0,0 +1,523 @@ +{ + "description": "The Replay Database", + "root_folder": "/idiap/group/replay/database/protocols/replayattack-database", + "protocols": [ + { + "name": "grandtest", + "template": "simple_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": false, + "protocol": "grandtest" + } + }, + "dev_probes": { + "view": "All", + "parameters": { + "group": "devel", + "enroll": false, + "protocol": "grandtest" + } + }, + "test_probes": { + "view": "All", + "parameters": { + "group": "test", + "enroll": false, + "protocol": "grandtest" + } + } + } + }, + { + "name": "print", + "template": "simple_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": false, + "protocol": "print" + } + }, + "dev_probes": { + "view": "All", + "parameters": { + "group": "devel", + "enroll": false, + "protocol": "print" + } + }, + "test_probes": { + "view": "All", + "parameters": { + "group": "test", + "enroll": false, + "protocol": "print" + } + } + } + }, + { + "name": "photo", + "template": "simple_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": false, + "protocol": "photo" + } + }, + "dev_probes": { + "view": "All", + "parameters": { + "group": "devel", + "enroll": false, + "protocol": "photo" + } + }, + "test_probes": { + "view": "All", + "parameters": { + "group": "test", + "enroll": false, + "protocol": "photo" + } + } + } + }, + { + "name": "video", + "template": "simple_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": false, + "protocol": "video" + } + }, + "dev_probes": { + "view": "All", + "parameters": { + "group": "devel", + "enroll": false, + "protocol": "video" + } + }, + "test_probes": { + "view": "All", + "parameters": { + "group": "test", + "enroll": false, + "protocol": "video" + } + } + } + }, + { + "name": "mobile", + "template": "simple_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": false, + "protocol": "mobile" + } + }, + "dev_probes": { + "view": "All", + "parameters": { + "group": "devel", + "enroll": false, + "protocol": "mobile" + } + }, + "test_probes": { + "view": "All", + "parameters": { + "group": "test", + "enroll": false, + "protocol": "mobile" + } + } + } + }, + { + "name": "highdef", + "template": "simple_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": false, + "protocol": "highdef" + } + }, + "dev_probes": { + "view": "All", + "parameters": { + "group": "devel", + "enroll": false, + "protocol": "highdef" + } + }, + "test_probes": { + "view": "All", + "parameters": { + "group": "test", + "enroll": false, + "protocol": "highdef" + } + } + } + }, + { + "name": "verification_grandtest", + "template": "advanced_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": true, + "protocol": "grandtest" + } + }, + "dev_templates": { + "view": "Templates", + "parameters": { + "group": "devel", + "protocol": "grandtest" + } + }, + "dev_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "devel", + "protocol": "grandtest" + } + }, + "dev_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "devel", + "protocol": "grandtest" + } + }, + "test_templates": { + "view": "Templates", + "parameters": { + "group": "test", + "protocol": "grandtest" + } + }, + "test_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "test", + "protocol": "grandtest" + } + }, + "test_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "test", + "protocol": "grandtest" + } + } + } + }, + { + "name": "verification_print", + "template": "advanced_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": true, + "protocol": "print" + } + }, + "dev_templates": { + "view": "Templates", + "parameters": { + "group": "devel", + "protocol": "print" + } + }, + "dev_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "devel", + "protocol": "print" + } + }, + "dev_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "devel", + "protocol": "print" + } + }, + "test_templates": { + "view": "Templates", + "parameters": { + "group": "test", + "protocol": "print" + } + }, + "test_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "test", + "protocol": "print" + } + }, + "test_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "test", + "protocol": "print" + } + } + } + }, + { + "name": "verification_photo", + "template": "advanced_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": true, + "protocol": "photo" + } + }, + "dev_templates": { + "view": "Templates", + "parameters": { + "group": "devel", + "protocol": "photo" + } + }, + "dev_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "devel", + "protocol": "photo" + } + }, + "dev_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "devel", + "protocol": "photo" + } + }, + "test_templates": { + "view": "Templates", + "parameters": { + "group": "test", + "protocol": "photo" + } + }, + "test_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "test", + "protocol": "photo" + } + }, + "test_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "test", + "protocol": "photo" + } + } + } + }, + { + "name": "verification_video", + "template": "advanced_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": true, + "protocol": "video" + } + }, + "dev_templates": { + "view": "Templates", + "parameters": { + "group": "devel", + "protocol": "video" + } + }, + "dev_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "devel", + "protocol": "video" + } + }, + "dev_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "devel", + "protocol": "video" + } + }, + "test_templates": { + "view": "Templates", + "parameters": { + "group": "test", + "protocol": "video" + } + }, + "test_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "test", + "protocol": "video" + } + }, + "test_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "test", + "protocol": "video" + } + } + } + }, + { + "name": "verification_mobile", + "template": "advanced_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": true, + "protocol": "mobile" + } + }, + "dev_templates": { + "view": "Templates", + "parameters": { + "group": "devel", + "protocol": "mobile" + } + }, + "dev_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "devel", + "protocol": "mobile" + } + }, + "dev_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "devel", + "protocol": "mobile" + } + }, + "test_templates": { + "view": "Templates", + "parameters": { + "group": "test", + "protocol": "mobile" + } + }, + "test_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "test", + "protocol": "mobile" + } + }, + "test_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "test", + "protocol": "mobile" + } + } + } + }, + { + "name": "verification_highdef", + "template": "advanced_face_antispoofing/1", + "views": { + "train": { + "view": "All", + "parameters": { + "group": "train", + "enroll": true, + "protocol": "highdef" + } + }, + "dev_templates": { + "view": "Templates", + "parameters": { + "group": "devel", + "protocol": "highdef" + } + }, + "dev_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "devel", + "protocol": "highdef" + } + }, + "dev_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "devel", + "protocol": "highdef" + } + }, + "test_templates": { + "view": "Templates", + "parameters": { + "group": "test", + "protocol": "highdef" + } + }, + "test_probes_real": { + "view": "ProbesReal", + "parameters": { + "group": "test", + "protocol": "highdef" + } + }, + "test_probes_attack": { + "view": "ProbesAttack", + "parameters": { + "group": "test", + "protocol": "highdef" + } + } + } + } + ], + "schema_version": 2 +} \ No newline at end of file diff --git a/advanced/databases/replay/5.py b/advanced/databases/replay/5.py new file mode 100644 index 0000000000000000000000000000000000000000..2b96eceba90e79f96003223e8b0629d7df0aef1e --- /dev/null +++ b/advanced/databases/replay/5.py @@ -0,0 +1,576 @@ +############################################################################### +# # +# Copyright (c) 2018 Idiap Research Institute, http://www.idiap.ch/ # +# Contact: beat.support@idiap.ch # +# # +# This file is part of the beat.examples module of the BEAT platform. # +# # +# Commercial License Usage # +# Licensees holding valid commercial BEAT licenses may use this file in # +# accordance with the terms contained in a written agreement between you # +# and Idiap. For further information contact tto@idiap.ch # +# # +# Alternatively, this file may be used under the terms of the GNU Affero # +# Public License version 3 as published by the Free Software and appearing # +# in the file LICENSE.AGPL included in the packaging of this file. # +# The BEAT platform is distributed in the hope that it will be useful, but # +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # +# or FITNESS FOR A PARTICULAR PURPOSE. # +# # +# You should have received a copy of the GNU Affero Public License along # +# with the BEAT platform. If not, see http://www.gnu.org/licenses/. # +# # +############################################################################### + +import numpy as np +from collections import namedtuple + +from beat.backend.python.database import View + +import bob.io.base +import bob.io.video +import bob.db.replay + +from bob.db.replay.driver import Interface + +INFO = Interface() +SQLITE_FILE = INFO.files()[0] + + +#---------------------------------------------------------- + + +class All(View): + """Outputs: + - video: "{{ system_user.username }}/array_4d_uint8/1" + - annotations: "{{ system_user.username }}/bounding_box_video/1" + - file_id: "{{ system_user.username }}/uint64/1" + - client_id: "{{ system_user.username }}/uint64/1" + - attack_support: "{{ system_user.username }}/text/1" + - class: "{{ system_user.username }}/text/1" + + One "file_id" is associated with a given "video". + One "annotations" is associated with a given "video". + Several "video" are associated with a given "client_id". + Several "client_id" are associated with a given "class". + Several "attack_support" are associated with a given "class". + + --------------- --------------- --------------- --------------- --------------- --------------- + | video | | video | | video | | video | | video | | video | + --------------- --------------- --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- --------------- --------------- + | annotations | | annotations | | annotations | | annotations | | annotations | | annotations | + --------------- --------------- --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- --------------- --------------- + | file_id | | file_id | | file_id | | file_id | | file_id | | file_id | + --------------- --------------- --------------- --------------- --------------- --------------- + ------------------------------- ------------------------------- ------------------------------- + | client_id | | client_id | | client_id | + ------------------------------- ------------------------------- ------------------------------- + --------------------------------------------------------------- ------------------------------- + | attack_support | | attack_support | + --------------------------------------------------------------- ------------------------------- + ----------------------------------------------------------------------------------------------- + | class | + ----------------------------------------------------------------------------------------------- + """ + + def __init__(self): + super(All, self) + self.output_member_map = {'class': 'cls'} + + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['cls', 'attack_support', 'client_id', 'file_id', + 'annotations', 'video']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.replay.Database() + + objs = [] + + if parameters['enroll']: + objs.extend([ ('enroll', '', x) + for x in sorted(db.objects(protocol=parameters['protocol'], + groups=parameters['group'], + cls='enroll'), + key=lambda x: (x.client_id, x.id)) + ]) + + objs.extend([ ('real', '', x) + for x in sorted(db.objects(protocol=parameters['protocol'], + groups=parameters['group'], + cls='real'), + key=lambda x: (x.client_id, x.id)) + ]) + + objs.extend([ ('attack', 'fixed', x) + for x in sorted(db.objects(protocol=parameters['protocol'], + groups=parameters['group'], + cls='attack', + support='fixed'), + key=lambda x: (x.client_id, x.id)) + ]) + + objs.extend([ ('attack', 'hand', x) + for x in sorted(db.objects(protocol=parameters['protocol'], + groups=parameters['group'], + cls='attack', + support='hand'), + key=lambda x: (x.client_id, x.id)) + ]) + + + return [ Entry(x[0], x[1], x[2].client_id, x[2].id, x[2].bbx(root_folder), + x[2].videofile(root_folder)) + for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'class': + return { + 'text': str(obj.cls) + } + + elif output == 'attack_support': + return { + 'text': str(obj.attack_support) + } + + elif output == 'client_id': + return { + 'value': np.uint64(obj.client_id) + } + + elif output == 'file_id': + return { + 'value': np.uint64(obj.file_id) + } + + elif output == 'annotations': + annotations_list = [] + for annotation in obj.annotations: + annotations_list.append({ + 'frame_id': np.uint64(annotation[0]), + 'top-left-x': np.int32(annotation[1]), + 'top-left-y': np.int32(annotation[2]), + 'width': np.int32(annotation[3]), + 'height': np.int32(annotation[4]) + }) + + return { + 'value': annotations_list + } + + elif output == 'video': + return { + 'value': bob.io.base.load(obj.video) + } + + +#---------------------------------------------------------- + + +class Templates(View): + """Outputs: + - video: "{{ system_user.username }}/array_4d_uint8/1" + - annotations: "{{ system_user.username }}/bounding_box_video/1" + - file_id: "{{ system_user.username }}/uint64/1" + - template_id: "{{ system_user.username }}/uint64/1" + - client_id: "{{ system_user.username }}/uint64/1" + + One "file_id" is associated with a given "video". + One "annotations" is associated with a given "video". + Several "video" are associated with a given "template_id". + Several "template_id" are associated with a given "client_id". + + --------------- --------------- --------------- --------------- + | video | | video | | video | | video | + --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- + | annotations | | annotations | | annotations | | annotations | + --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- + | file_id | | file_id | | file_id | | file_id | + --------------- --------------- --------------- --------------- + ------------------------------- ------------------------------- + | template_id | | template_id | + ------------------------------- ------------------------------- + --------------------------------------------------------------- + | client_id | + --------------------------------------------------------------- + + Note: for this particular database, there is only one "template_id" + per "client_id". + """ + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['client_id', 'template_id', 'file_id', + 'annotations', 'video']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.replay.Database() + + objs = sorted(db.objects(protocol=parameters['protocol'], + groups=[parameters['group']], + cls='enroll'), + key=lambda x: (x.client_id, x.id)) + + + return [ Entry(x.client_id, x.client_id, x.id, x.bbx(root_folder), + x.videofile(root_folder)) + for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'client_id': + return { + 'value': np.uint64(obj.client_id) + } + + elif output == 'template_id': + return { + 'value': np.uint64(obj.template_id) + } + + elif output == 'file_id': + return { + 'value': np.uint64(obj.file_id) + } + + elif output == 'annotations': + annotations_list = [] + for annotation in obj.annotations: + annotations_list.append({ + 'frame_id': np.uint64(annotation[0]), + 'top-left-x': np.int32(annotation[1]), + 'top-left-y': np.int32(annotation[2]), + 'width': np.int32(annotation[3]), + 'height': np.int32(annotation[4]) + }) + + return { + 'value': annotations_list + } + + elif output == 'video': + return { + 'value': bob.io.base.load(obj.video) + } + + +#---------------------------------------------------------- + + +class ProbesReal(View): + """Outputs: + - video: "{{ system_user.username }}/array_4d_uint8/1" + - annotations: "{{ system_user.username }}/bounding_box_video/1" + - file_id: "{{ system_user.username }}/uint64/1" + - probe_id: "{{ system_user.username }}/uint64/1" + - client_id: "{{ system_user.username }}/uint64/1" + - template_ids: "{{ system_user.username }}/array_1d_uint64/1" + + One "file_id" is associated with a given "video". + One "annotations" is associated with a given "video". + One "probe_id" is associated with a given "video". + Several "video" are associated with a given "client_id". + Several "client_id" are associated with a given "template_ids". + + --------------- --------------- --------------- --------------- + | video | | video | | video | | video | + --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- + | annotations | | annotations | | annotations | | annotations | + --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- + | file_id | | file_id | | file_id | | file_id | + --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- + | probe_id | | probe_id | | probe_id | | probe_id | + --------------- --------------- --------------- --------------- + ------------------------------- ------------------------------- + | client_id | | client_id | + ------------------------------- ------------------------------- + --------------------------------------------------------------- + | template_ids | + --------------------------------------------------------------- + + Note: for this particular database, there is only one "template_ids" + """ + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['template_ids', 'client_id', 'probe_id', 'file_id', + 'annotations', 'video']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.replay.Database() + + template_ids = sorted([c.id for c in db.clients() if c.set == parameters['group']]) + + objs = sorted(db.objects(protocol=parameters['protocol'], + groups=[parameters['group']], + cls='real'), + key=lambda x: (x.client_id, x.id)) + + + return [ Entry(template_ids, x.client_id, x.id, x.id, x.bbx(root_folder), + x.videofile(root_folder)) + for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'template_ids': + return { + 'value': np.uint64(obj.template_ids) + } + + elif output == 'client_id': + return { + 'value': np.uint64(obj.client_id) + } + + elif output == 'probe_id': + return { + 'value': np.uint64(obj.probe_id) + } + + elif output == 'file_id': + return { + 'value': np.uint64(obj.file_id) + } + + elif output == 'annotations': + annotations_list = [] + for annotation in obj.annotations: + annotations_list.append({ + 'frame_id': np.uint64(annotation[0]), + 'top-left-x': np.int32(annotation[1]), + 'top-left-y': np.int32(annotation[2]), + 'width': np.int32(annotation[3]), + 'height': np.int32(annotation[4]) + }) + + return { + 'value': annotations_list + } + + elif output == 'video': + return { + 'value': bob.io.base.load(obj.video) + } + + +#---------------------------------------------------------- + + +class ProbesAttack(View): + """Outputs: + - video: "{{ system_user.username }}/array_4d_uint8/1" + - annotations: "{{ system_user.username }}/bounding_box_video/1" + - file_id: "{{ system_user.username }}/uint64/1" + - probe_id: "{{ system_user.username }}/uint64/1" + - client_id: "{{ system_user.username }}/uint64/1" + - attack_support: "{{ system_user.username }}/text/1" + - template_ids: "{{ system_user.username }}/array_1d_uint64/1" + + One "file_id" is associated with a given "video". + One "annotations" is associated with a given "video". + One "probe_id" is associated with a given "video". + Several "video" are associated with a given "client_id". + Several "client_id" are associated with a given "template_ids". + Several "template_ids" are associated with a given "attack_support". + + --------------- --------------- --------------- --------------- --------------- --------------- + | video | | video | | video | | video | | video | | video | + --------------- --------------- --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- --------------- --------------- + | annotations | | annotations | | annotations | | annotations | | annotations | | annotations | + --------------- --------------- --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- --------------- --------------- + | file_id | | file_id | | file_id | | file_id | | file_id | | file_id | + --------------- --------------- --------------- --------------- --------------- --------------- + --------------- --------------- --------------- --------------- --------------- --------------- + | probe_id | | probe_id | | probe_id | | probe_id | | probe_id | | probe_id | + --------------- --------------- --------------- --------------- --------------- --------------- + ------------------------------- ------------------------------- ------------------------------- + | client_id | | client_id | | client_id | + ------------------------------- ------------------------------- ------------------------------- + --------------------------------------------------------------- ------------------------------- + | template_ids | | template_ids | + --------------------------------------------------------------- ------------------------------- + ----------------------------------------------------------------------------------------------- + | attack_support | + ----------------------------------------------------------------------------------------------- + """ + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['attack_support', 'template_ids', 'client_id', + 'probe_id', 'file_id', 'annotations', 'video']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.replay.Database() + + objs = [] + + objs.extend([ ('fixed', x) + for x in sorted(db.objects(protocol=parameters['protocol'], + groups=parameters['group'], + cls='attack', + support='fixed'), + key=lambda x: (x.client_id, x.id)) + ]) + + objs.extend([ ('hand', x) + for x in sorted(db.objects(protocol=parameters['protocol'], + groups=parameters['group'], + cls='attack', + support='hand'), + key=lambda x: (x.client_id, x.id)) + ]) + + return [ Entry(x[0], [ x[1].client_id ], x[1].client_id, x[1].id, x[1].id, + x[1].bbx(root_folder), x[1].videofile(root_folder)) + for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'attack_support': + return { + 'text': str(obj.attack_support) + } + + elif output == 'template_ids': + return { + 'value': np.uint64(obj.template_ids) + } + + elif output == 'client_id': + return { + 'value': np.uint64(obj.client_id) + } + + elif output == 'probe_id': + return { + 'value': np.uint64(obj.probe_id) + } + + elif output == 'file_id': + return { + 'value': np.uint64(obj.file_id) + } + + elif output == 'annotations': + annotations_list = [] + for annotation in obj.annotations: + annotations_list.append({ + 'frame_id': np.uint64(annotation[0]), + 'top-left-x': np.int32(annotation[1]), + 'top-left-y': np.int32(annotation[2]), + 'width': np.int32(annotation[3]), + 'height': np.int32(annotation[4]) + }) + + return { + 'value': annotations_list + } + + elif output == 'video': + return { + 'value': bob.io.base.load(obj.video) + } + + +#---------------------------------------------------------- + + +def setup_tests(): + def mock_load(filename): + return np.ndarray((5, 3, 10, 20), dtype=np.uint8) + + def mock_bbx(obj, directory): + return np.array([(0, 1, 2, 3, 4, 5), (1, 10, 20, 30, 40, 50)]) + + bob.io.base.load = mock_load + bob.db.replay.File.bbx = mock_bbx + + +#---------------------------------------------------------- + + +# Test the behavior of the views (on fake data) +if __name__ == '__main__': + + setup_tests() + + view = All() + view.objs = view.index( + root_folder='', + parameters=dict( + protocol="grandtest", + group="train", + enroll=False, + ) + ) + view.get('class', 0) + view.get('attack_support', 0) + view.get('client_id', 0) + view.get('file_id', 0) + view.get('annotations', 0) + view.get('video', 0) + + + view = Templates() + view.objs = view.index( + root_folder='', + parameters=dict( + protocol="grandtest", + group="devel", + ) + ) + view.get('client_id', 0) + view.get('template_id', 0) + view.get('file_id', 0) + view.get('annotations', 0) + view.get('video', 0) + + + view = ProbesReal() + view.objs = view.index( + root_folder='', + parameters=dict( + protocol="grandtest", + group="devel", + ) + ) + view.get('template_ids', 0) + view.get('client_id', 0) + view.get('probe_id', 0) + view.get('file_id', 0) + view.get('annotations', 0) + view.get('video', 0) + + + view = ProbesAttack() + view.objs = view.index( + root_folder='', + parameters=dict( + protocol="grandtest", + group="devel", + ) + ) + view.get('attack_support', 0) + view.get('template_ids', 0) + view.get('client_id', 0) + view.get('probe_id', 0) + view.get('file_id', 0) + view.get('annotations', 0) + view.get('video', 0) diff --git a/advanced/databases/replay/5.rst b/advanced/databases/replay/5.rst new file mode 100644 index 0000000000000000000000000000000000000000..cb450c05cd275bffca25d1fde72d216a27033522 --- /dev/null +++ b/advanced/databases/replay/5.rst @@ -0,0 +1 @@ +The Replay Database \ No newline at end of file