Repository: comic/grand-challenge.org

Issue:
Multiple 2D bounding boxes
**Is your feature request related to a problem? Please describe.**
I am currently working on a reader study where I would like users to indicate adhesions on abdominal MRI with bounding boxes. There are cases without adhesions, with one adhesion, or multiple. Currently, I can not make one question to cover all cases.

**Describe the solution you'd like**
An option for multiple 2D bounding boxes as answer type.

**Describe alternatives you've considered**
Right now I circumvent this issue by adding many single bounding box questions.



Discussion:

Resolving patch:
diff --git a/app/grandchallenge/reader_studies/migrations/0025_auto_20201123_1414.py b/app/grandchallenge/reader_studies/migrations/0025_auto_20201123_1414.py
new file mode 100644
--- /dev/null
+++ b/app/grandchallenge/reader_studies/migrations/0025_auto_20201123_1414.py
@@ -0,0 +1,668 @@
+# Generated by Django 3.1.1 on 2020-11-23 14:14
+
+from django.db import migrations, models
+
+import grandchallenge.core.validators
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("reader_studies", "0024_readerstudy_validate_hanging_list"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="answer",
+            name="answer",
+            field=models.JSONField(
+                null=True,
+                validators=[
+                    grandchallenge.core.validators.JSONSchemaValidator(
+                        schema={
+                            "$schema": "http://json-schema.org/draft-07/schema#",
+                            "anyOf": [
+                                {"$ref": "#/definitions/null"},
+                                {"$ref": "#/definitions/STXT"},
+                                {"$ref": "#/definitions/MTXT"},
+                                {"$ref": "#/definitions/BOOL"},
+                                {"$ref": "#/definitions/HEAD"},
+                                {"$ref": "#/definitions/2DBB"},
+                                {"$ref": "#/definitions/DIST"},
+                                {"$ref": "#/definitions/MDIS"},
+                                {"$ref": "#/definitions/POIN"},
+                                {"$ref": "#/definitions/MPOI"},
+                                {"$ref": "#/definitions/POLY"},
+                                {"$ref": "#/definitions/MPOL"},
+                                {"$ref": "#/definitions/CHOI"},
+                                {"$ref": "#/definitions/MCHO"},
+                                {"$ref": "#/definitions/MCHD"},
+                                {"$ref": "#/definitions/M2DB"},
+                            ],
+                            "definitions": {
+                                "2D-bounding-box-object": {
+                                    "properties": {
+                                        "corners": {
+                                            "items": {
+                                                "items": {"type": "number"},
+                                                "maxItems": 3,
+                                                "minItems": 3,
+                                                "type": "array",
+                                            },
+                                            "maxItems": 4,
+                                            "minItems": 4,
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                    },
+                                    "required": ["corners"],
+                                    "type": "object",
+                                },
+                                "2DBB": {
+                                    "properties": {
+                                        "corners": {
+                                            "items": {
+                                                "items": {"type": "number"},
+                                                "maxItems": 3,
+                                                "minItems": 3,
+                                                "type": "array",
+                                            },
+                                            "maxItems": 4,
+                                            "minItems": 4,
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "type": {"enum": ["2D bounding box"]},
+                                    },
+                                    "required": ["version", "type", "corners"],
+                                    "type": "object",
+                                },
+                                "BOOL": {"type": "boolean"},
+                                "CHOI": {"type": "number"},
+                                "DIST": {
+                                    "properties": {
+                                        "end": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "start": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "type": {
+                                            "enum": ["Distance measurement"]
+                                        },
+                                    },
+                                    "required": [
+                                        "version",
+                                        "type",
+                                        "start",
+                                        "end",
+                                    ],
+                                    "type": "object",
+                                },
+                                "HEAD": {"type": "null"},
+                                "M2DB": {
+                                    "properties": {
+                                        "boxes": {
+                                            "items": {
+                                                "allOf": [
+                                                    {
+                                                        "$ref": "#/definitions/2D-bounding-box-object"
+                                                    }
+                                                ]
+                                            },
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "type": {
+                                            "enum": [
+                                                "Multiple 2D bounding boxes"
+                                            ]
+                                        },
+                                    },
+                                    "required": ["version", "type", "boxes"],
+                                    "type": "object",
+                                },
+                                "MCHD": {
+                                    "items": {"type": "number"},
+                                    "type": "array",
+                                },
+                                "MCHO": {
+                                    "items": {"type": "number"},
+                                    "type": "array",
+                                },
+                                "MDIS": {
+                                    "properties": {
+                                        "lines": {
+                                            "items": {
+                                                "allOf": [
+                                                    {
+                                                        "$ref": "#/definitions/line-object"
+                                                    }
+                                                ]
+                                            },
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "type": {
+                                            "enum": [
+                                                "Multiple distance measurements"
+                                            ]
+                                        },
+                                    },
+                                    "required": ["version", "type", "lines"],
+                                    "type": "object",
+                                },
+                                "MPOI": {
+                                    "properties": {
+                                        "name": {"type": "string"},
+                                        "points": {
+                                            "items": {
+                                                "allOf": [
+                                                    {
+                                                        "$ref": "#/definitions/point-object"
+                                                    }
+                                                ]
+                                            },
+                                            "type": "array",
+                                        },
+                                        "type": {"enum": ["Multiple points"]},
+                                    },
+                                    "required": ["version", "type", "points"],
+                                    "type": "object",
+                                },
+                                "MPOL": {
+                                    "properties": {
+                                        "name": {"type": "string"},
+                                        "polygons": {
+                                            "items": {
+                                                "$ref": "#/definitions/polygon-object"
+                                            },
+                                            "type": "array",
+                                        },
+                                        "type": {
+                                            "enum": ["Multiple polygons"]
+                                        },
+                                    },
+                                    "required": [
+                                        "type",
+                                        "version",
+                                        "polygons",
+                                    ],
+                                    "type": "object",
+                                },
+                                "MTXT": {"type": "string"},
+                                "POIN": {
+                                    "properties": {
+                                        "name": {"type": "string"},
+                                        "point": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "type": {"enum": ["Point"]},
+                                    },
+                                    "required": ["version", "type", "point"],
+                                    "type": "object",
+                                },
+                                "POLY": {
+                                    "properties": {
+                                        "groups": {
+                                            "items": {"type": "string"},
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "path_points": {
+                                            "items": {
+                                                "items": {"type": "number"},
+                                                "maxItems": 3,
+                                                "minItems": 3,
+                                                "type": "array",
+                                            },
+                                            "type": "array",
+                                        },
+                                        "seed_point": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "sub_type": {"type": "string"},
+                                    },
+                                    "required": [
+                                        "name",
+                                        "seed_point",
+                                        "path_points",
+                                        "sub_type",
+                                        "groups",
+                                        "version",
+                                    ],
+                                    "type": "object",
+                                },
+                                "STXT": {"type": "string"},
+                                "line-object": {
+                                    "properties": {
+                                        "end": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "start": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                    },
+                                    "required": ["start", "end"],
+                                    "type": "object",
+                                },
+                                "null": {"type": "null"},
+                                "point-object": {
+                                    "properties": {
+                                        "name": {"type": "string"},
+                                        "point": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                    },
+                                    "required": ["point"],
+                                    "type": "object",
+                                },
+                                "polygon-object": {
+                                    "properties": {
+                                        "groups": {
+                                            "items": {"type": "string"},
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "path_points": {
+                                            "items": {
+                                                "items": {"type": "number"},
+                                                "maxItems": 3,
+                                                "minItems": 3,
+                                                "type": "array",
+                                            },
+                                            "type": "array",
+                                        },
+                                        "seed_point": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "sub_type": {"type": "string"},
+                                    },
+                                    "required": [
+                                        "name",
+                                        "seed_point",
+                                        "path_points",
+                                        "sub_type",
+                                        "groups",
+                                    ],
+                                    "type": "object",
+                                },
+                            },
+                            "properties": {
+                                "version": {
+                                    "additionalProperties": {"type": "number"},
+                                    "required": ["major", "minor"],
+                                    "type": "object",
+                                }
+                            },
+                        }
+                    )
+                ],
+            ),
+        ),
+        migrations.AlterField(
+            model_name="historicalanswer",
+            name="answer",
+            field=models.JSONField(
+                null=True,
+                validators=[
+                    grandchallenge.core.validators.JSONSchemaValidator(
+                        schema={
+                            "$schema": "http://json-schema.org/draft-07/schema#",
+                            "anyOf": [
+                                {"$ref": "#/definitions/null"},
+                                {"$ref": "#/definitions/STXT"},
+                                {"$ref": "#/definitions/MTXT"},
+                                {"$ref": "#/definitions/BOOL"},
+                                {"$ref": "#/definitions/HEAD"},
+                                {"$ref": "#/definitions/2DBB"},
+                                {"$ref": "#/definitions/DIST"},
+                                {"$ref": "#/definitions/MDIS"},
+                                {"$ref": "#/definitions/POIN"},
+                                {"$ref": "#/definitions/MPOI"},
+                                {"$ref": "#/definitions/POLY"},
+                                {"$ref": "#/definitions/MPOL"},
+                                {"$ref": "#/definitions/CHOI"},
+                                {"$ref": "#/definitions/MCHO"},
+                                {"$ref": "#/definitions/MCHD"},
+                                {"$ref": "#/definitions/M2DB"},
+                            ],
+                            "definitions": {
+                                "2D-bounding-box-object": {
+                                    "properties": {
+                                        "corners": {
+                                            "items": {
+                                                "items": {"type": "number"},
+                                                "maxItems": 3,
+                                                "minItems": 3,
+                                                "type": "array",
+                                            },
+                                            "maxItems": 4,
+                                            "minItems": 4,
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                    },
+                                    "required": ["corners"],
+                                    "type": "object",
+                                },
+                                "2DBB": {
+                                    "properties": {
+                                        "corners": {
+                                            "items": {
+                                                "items": {"type": "number"},
+                                                "maxItems": 3,
+                                                "minItems": 3,
+                                                "type": "array",
+                                            },
+                                            "maxItems": 4,
+                                            "minItems": 4,
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "type": {"enum": ["2D bounding box"]},
+                                    },
+                                    "required": ["version", "type", "corners"],
+                                    "type": "object",
+                                },
+                                "BOOL": {"type": "boolean"},
+                                "CHOI": {"type": "number"},
+                                "DIST": {
+                                    "properties": {
+                                        "end": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "start": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "type": {
+                                            "enum": ["Distance measurement"]
+                                        },
+                                    },
+                                    "required": [
+                                        "version",
+                                        "type",
+                                        "start",
+                                        "end",
+                                    ],
+                                    "type": "object",
+                                },
+                                "HEAD": {"type": "null"},
+                                "M2DB": {
+                                    "properties": {
+                                        "boxes": {
+                                            "items": {
+                                                "allOf": [
+                                                    {
+                                                        "$ref": "#/definitions/2D-bounding-box-object"
+                                                    }
+                                                ]
+                                            },
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "type": {
+                                            "enum": [
+                                                "Multiple 2D bounding boxes"
+                                            ]
+                                        },
+                                    },
+                                    "required": ["version", "type", "boxes"],
+                                    "type": "object",
+                                },
+                                "MCHD": {
+                                    "items": {"type": "number"},
+                                    "type": "array",
+                                },
+                                "MCHO": {
+                                    "items": {"type": "number"},
+                                    "type": "array",
+                                },
+                                "MDIS": {
+                                    "properties": {
+                                        "lines": {
+                                            "items": {
+                                                "allOf": [
+                                                    {
+                                                        "$ref": "#/definitions/line-object"
+                                                    }
+                                                ]
+                                            },
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "type": {
+                                            "enum": [
+                                                "Multiple distance measurements"
+                                            ]
+                                        },
+                                    },
+                                    "required": ["version", "type", "lines"],
+                                    "type": "object",
+                                },
+                                "MPOI": {
+                                    "properties": {
+                                        "name": {"type": "string"},
+                                        "points": {
+                                            "items": {
+                                                "allOf": [
+                                                    {
+                                                        "$ref": "#/definitions/point-object"
+                                                    }
+                                                ]
+                                            },
+                                            "type": "array",
+                                        },
+                                        "type": {"enum": ["Multiple points"]},
+                                    },
+                                    "required": ["version", "type", "points"],
+                                    "type": "object",
+                                },
+                                "MPOL": {
+                                    "properties": {
+                                        "name": {"type": "string"},
+                                        "polygons": {
+                                            "items": {
+                                                "$ref": "#/definitions/polygon-object"
+                                            },
+                                            "type": "array",
+                                        },
+                                        "type": {
+                                            "enum": ["Multiple polygons"]
+                                        },
+                                    },
+                                    "required": [
+                                        "type",
+                                        "version",
+                                        "polygons",
+                                    ],
+                                    "type": "object",
+                                },
+                                "MTXT": {"type": "string"},
+                                "POIN": {
+                                    "properties": {
+                                        "name": {"type": "string"},
+                                        "point": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "type": {"enum": ["Point"]},
+                                    },
+                                    "required": ["version", "type", "point"],
+                                    "type": "object",
+                                },
+                                "POLY": {
+                                    "properties": {
+                                        "groups": {
+                                            "items": {"type": "string"},
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "path_points": {
+                                            "items": {
+                                                "items": {"type": "number"},
+                                                "maxItems": 3,
+                                                "minItems": 3,
+                                                "type": "array",
+                                            },
+                                            "type": "array",
+                                        },
+                                        "seed_point": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "sub_type": {"type": "string"},
+                                    },
+                                    "required": [
+                                        "name",
+                                        "seed_point",
+                                        "path_points",
+                                        "sub_type",
+                                        "groups",
+                                        "version",
+                                    ],
+                                    "type": "object",
+                                },
+                                "STXT": {"type": "string"},
+                                "line-object": {
+                                    "properties": {
+                                        "end": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "start": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                    },
+                                    "required": ["start", "end"],
+                                    "type": "object",
+                                },
+                                "null": {"type": "null"},
+                                "point-object": {
+                                    "properties": {
+                                        "name": {"type": "string"},
+                                        "point": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                    },
+                                    "required": ["point"],
+                                    "type": "object",
+                                },
+                                "polygon-object": {
+                                    "properties": {
+                                        "groups": {
+                                            "items": {"type": "string"},
+                                            "type": "array",
+                                        },
+                                        "name": {"type": "string"},
+                                        "path_points": {
+                                            "items": {
+                                                "items": {"type": "number"},
+                                                "maxItems": 3,
+                                                "minItems": 3,
+                                                "type": "array",
+                                            },
+                                            "type": "array",
+                                        },
+                                        "seed_point": {
+                                            "items": {"type": "number"},
+                                            "maxItems": 3,
+                                            "minItems": 3,
+                                            "type": "array",
+                                        },
+                                        "sub_type": {"type": "string"},
+                                    },
+                                    "required": [
+                                        "name",
+                                        "seed_point",
+                                        "path_points",
+                                        "sub_type",
+                                        "groups",
+                                    ],
+                                    "type": "object",
+                                },
+                            },
+                            "properties": {
+                                "version": {
+                                    "additionalProperties": {"type": "number"},
+                                    "required": ["major", "minor"],
+                                    "type": "object",
+                                }
+                            },
+                        }
+                    )
+                ],
+            ),
+        ),
+        migrations.AlterField(
+            model_name="question",
+            name="answer_type",
+            field=models.CharField(
+                choices=[
+                    ("STXT", "Single line text"),
+                    ("MTXT", "Multi line text"),
+                    ("BOOL", "Bool"),
+                    ("HEAD", "Heading"),
+                    ("2DBB", "2D bounding box"),
+                    ("M2DB", "Multiple 2D bounding boxes"),
+                    ("DIST", "Distance measurement"),
+                    ("MDIS", "Multiple distance measurements"),
+                    ("POIN", "Point"),
+                    ("MPOI", "Multiple points"),
+                    ("POLY", "Polygon"),
+                    ("MPOL", "Multiple polygons"),
+                    ("CHOI", "Choice"),
+                    ("MCHO", "Multiple choice"),
+                    ("MCHD", "Multiple choice dropdown"),
+                ],
+                default="STXT",
+                max_length=4,
+            ),
+        ),
+    ]
diff --git a/app/grandchallenge/reader_studies/models.py b/app/grandchallenge/reader_studies/models.py
--- a/app/grandchallenge/reader_studies/models.py
+++ b/app/grandchallenge/reader_studies/models.py
@@ -987,6 +987,40 @@ def delete_reader_study_groups_hook(*_, instance: ReaderStudy, using, **__):
             },
             "required": ["type", "version", "polygons"],
         },
+        "2D-bounding-box-object": {
+            "type": "object",
+            "properties": {
+                "name": {"type": "string"},
+                "corners": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {"type": "number"},
+                        "minItems": 3,
+                        "maxItems": 3,
+                    },
+                    "minItems": 4,
+                    "maxItems": 4,
+                },
+            },
+            "required": ["corners"],
+        },
+        "M2DB": {
+            "type": "object",
+            "properties": {
+                "name": {"type": "string"},
+                "type": {"enum": ["Multiple 2D bounding boxes"]},
+                "boxes": {
+                    "type": "array",
+                    "items": {
+                        "allOf": [
+                            {"$ref": "#/definitions/2D-bounding-box-object"}
+                        ]
+                    },
+                },
+            },
+            "required": ["version", "type", "boxes"],
+        },
     },
     "properties": {
         "version": {
@@ -1012,6 +1046,7 @@ def delete_reader_study_groups_hook(*_, instance: ReaderStudy, using, **__):
         {"$ref": "#/definitions/CHOI"},
         {"$ref": "#/definitions/MCHO"},
         {"$ref": "#/definitions/MCHD"},
+        {"$ref": "#/definitions/M2DB"},
     ],
 }
 
@@ -1022,6 +1057,7 @@ class Question(UUIDModel):
     ANSWER_TYPE_BOOL = "BOOL"
     ANSWER_TYPE_HEADING = "HEAD"
     ANSWER_TYPE_2D_BOUNDING_BOX = "2DBB"
+    ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES = "M2DB"
     ANSWER_TYPE_DISTANCE_MEASUREMENT = "DIST"
     ANSWER_TYPE_MULTIPLE_DISTANCE_MEASUREMENTS = "MDIS"
     ANSWER_TYPE_POINT = "POIN"
@@ -1038,6 +1074,7 @@ class Question(UUIDModel):
         (ANSWER_TYPE_BOOL, "Bool"),
         (ANSWER_TYPE_HEADING, "Heading"),
         (ANSWER_TYPE_2D_BOUNDING_BOX, "2D bounding box"),
+        (ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES, "Multiple 2D bounding boxes"),
         (ANSWER_TYPE_DISTANCE_MEASUREMENT, "Distance measurement"),
         (
             ANSWER_TYPE_MULTIPLE_DISTANCE_MEASUREMENTS,
@@ -1230,6 +1267,7 @@ def clean(self):
     def annotation_types(self):
         return [
             self.ANSWER_TYPE_2D_BOUNDING_BOX,
+            self.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES,
             self.ANSWER_TYPE_DISTANCE_MEASUREMENT,
             self.ANSWER_TYPE_MULTIPLE_DISTANCE_MEASUREMENTS,
             self.ANSWER_TYPE_POINT,


Test patch:
diff --git a/app/tests/algorithms_tests/test_views.py b/app/tests/algorithms_tests/test_views.py
--- a/app/tests/algorithms_tests/test_views.py
+++ b/app/tests/algorithms_tests/test_views.py
@@ -407,8 +407,6 @@ def test_algorithm_jobs_list_view(client):
     assert resp_new["recordsTotal"] == 50
     assert resp_new["data"] == resp["data"][::-1]
 
-    resp_new["data"] == resp["data"][::-1]
-
     response = get_view_for_user(
         viewname="algorithms:jobs-list",
         reverse_kwargs={"slug": slugify(alg.slug)},
diff --git a/app/tests/reader_studies_tests/test_api.py b/app/tests/reader_studies_tests/test_api.py
--- a/app/tests/reader_studies_tests/test_api.py
+++ b/app/tests/reader_studies_tests/test_api.py
@@ -291,6 +291,85 @@ def test_answer_creator_is_reader(client):
             '{"version": {"major": 1, "minor": 0}, "type": "2D bounding box", "name": "test_name", "corners": [[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 0, 0]]}',
             400,
         ),  # Valid json, but a string
+        (Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES, "", 400),
+        (Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES, True, 400),
+        (Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES, False, 400),
+        (Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES, 134, 400),
+        (Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES, "dsfuag", 400),
+        (Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES, {}, 400),
+        (
+            Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES,
+            {
+                "version": {"major": 1, "minor": 0},
+                "type": "Multiple 2D bounding boxes",
+                "name": "test_name",
+                "boxes": [
+                    {
+                        "corners": [
+                            [0, 0, 0],
+                            [10, 0, 0],
+                            [10, 10, 0],
+                            [0, 0, 0],
+                        ]
+                    }
+                ],
+            },
+            201,
+        ),
+        (
+            Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES,
+            {
+                "type": "2D bounding box",
+                "name": "test_name",
+                "boxes": [[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 0, 0]],
+            },
+            400,
+        ),
+        (
+            Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES,
+            {
+                "version": {"major": 1, "minor": 0},
+                "name": "test_name",
+                "boxes": [
+                    {
+                        "corners": [
+                            [0, 0, 0],
+                            [10, 0, 0],
+                            [10, 10, 0],
+                            [0, 0, 0],
+                        ]
+                    }
+                ],
+            },
+            400,
+        ),
+        (
+            Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES,
+            {
+                "version": {"major": 1, "minor": 0},
+                "type": "Multiple 2D bounding boxes",
+                "name": "test_name",
+                "boxes": [
+                    {
+                        "corners": [
+                            [0, 0, 0],
+                            [10, 0, 0],
+                            [10, 10, 0],
+                            [0, 0, 0],
+                        ]
+                    },
+                    {
+                        "corners": [
+                            [0, 0, 0],
+                            [10, 0, 0],
+                            [10, 10, 0],
+                            [0, 0, 0],
+                        ]
+                    },
+                ],
+            },
+            201,
+        ),
         (
             Question.ANSWER_TYPE_DISTANCE_MEASUREMENT,
             {
@@ -526,6 +605,7 @@ def test_answer_creator_is_reader(client):
         (Question.ANSWER_TYPE_BOOL, None, 400),
         (Question.ANSWER_TYPE_HEADING, None, 400),
         (Question.ANSWER_TYPE_2D_BOUNDING_BOX, None, 201),
+        (Question.ANSWER_TYPE_MULTIPLE_2D_BOUNDING_BOXES, None, 201),
         (Question.ANSWER_TYPE_DISTANCE_MEASUREMENT, None, 201),
         (Question.ANSWER_TYPE_MULTIPLE_DISTANCE_MEASUREMENTS, None, 201),
         (Question.ANSWER_TYPE_POINT, None, 201),