We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add support for multipolygons
Enable RV to handle geojson label stores that are encoded as multipolygons

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/rastervision/label_stores/object_detection_geojson_file.py`
Content:
```
1 import json
2 
3 import numpy as np
4 
5 from rastervision.core.box import Box
6 from rastervision.labels.object_detection_labels import (ObjectDetectionLabels)
7 from rastervision.label_stores.utils import (add_classes_to_geojson,
8                                              load_label_store_json)
9 from rastervision.label_stores.object_detection_label_store import (
10     ObjectDetectionLabelStore)
11 from rastervision.label_stores.utils import boxes_to_geojson
12 from rastervision.utils.files import str_to_file, NotWritableError
13 
14 
15 def geojson_to_labels(geojson_dict, crs_transformer, extent=None):
16     """Convert GeoJSON to ObjectDetectionLabels object.
17 
18     If extent is provided, filter out the boxes that lie "more than a little
19     bit" outside the extent.
20 
21     Args:
22         geojson_dict: dict in GeoJSON format
23         crs_transformer: used to convert map coords in geojson to pixel coords
24             in labels object
25         extent: Box in pixel coords
26 
27     Returns:
28         ObjectDetectionLabels
29     """
30     features = geojson_dict['features']
31     boxes = []
32     class_ids = []
33     scores = []
34 
35     for feature in features:
36         # Convert polygon to pixel coords and then convert to bounding box.
37         polygon = feature['geometry']['coordinates'][0]
38         polygon = [crs_transformer.map_to_pixel(p) for p in polygon]
39         xmin, ymin = np.min(polygon, axis=0)
40         xmax, ymax = np.max(polygon, axis=0)
41         boxes.append(Box(ymin, xmin, ymax, xmax))
42 
43         properties = feature['properties']
44         class_ids.append(properties['class_id'])
45         scores.append(properties.get('score', 1.0))
46 
47     boxes = np.array([box.npbox_format() for box in boxes], dtype=float)
48     class_ids = np.array(class_ids)
49     scores = np.array(scores)
50 
51     labels = ObjectDetectionLabels(boxes, class_ids, scores=scores)
52     if extent is not None:
53         labels = ObjectDetectionLabels.get_overlapping(
54             labels, extent, ioa_thresh=0.8, clip=True)
55     return labels
56 
57 
58 class ObjectDetectionGeoJSONFile(ObjectDetectionLabelStore):
59     def __init__(self,
60                  uri,
61                  crs_transformer,
62                  class_map,
63                  extent=None,
64                  readable=True,
65                  writable=False):
66         """Construct ObjectDetectionLabelStore backed by a GeoJSON file.
67 
68         Args:
69             uri: uri of GeoJSON file containing labels
70             crs_transformer: CRSTransformer to convert from map coords in label
71                 in GeoJSON file to pixel coords.
72             class_map: ClassMap used to infer class_ids from class_name
73                 (or label) field
74             extent: Box used to filter the labels by extent
75             readable: if True, expect the file to exist
76             writable: if True, allow writing to disk
77         """
78         self.uri = uri
79         self.crs_transformer = crs_transformer
80         self.class_map = class_map
81         self.readable = readable
82         self.writable = writable
83 
84         self.labels = ObjectDetectionLabels.make_empty()
85 
86         json_dict = load_label_store_json(uri, readable)
87         if json_dict:
88             geojson = add_classes_to_geojson(json_dict, class_map)
89             self.labels = geojson_to_labels(
90                 geojson, crs_transformer, extent=extent)
91 
92     def save(self):
93         """Save labels to URI if writable."""
94         if self.writable:
95             boxes = self.labels.get_boxes()
96             class_ids = self.labels.get_class_ids().tolist()
97             scores = self.labels.get_scores().tolist()
98             geojson_dict = boxes_to_geojson(
99                 boxes,
100                 class_ids,
101                 self.crs_transformer,
102                 self.class_map,
103                 scores=scores)
104             geojson_str = json.dumps(geojson_dict)
105             str_to_file(geojson_str, self.uri)
106         else:
107             raise NotWritableError('Cannot write with writable=False')
108
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/rastervision/label_stores/object_detection_geojson_file.py b/src/rastervision/label_stores/object_detection_geojson_file.py
--- a/src/rastervision/label_stores/object_detection_geojson_file.py
+++ b/src/rastervision/label_stores/object_detection_geojson_file.py
@@ -32,9 +32,7 @@
     class_ids = []
     scores = []
 
-    for feature in features:
-        # Convert polygon to pixel coords and then convert to bounding box.
-        polygon = feature['geometry']['coordinates'][0]
+    def polygon_to_label(polygon, crs_transformer):
         polygon = [crs_transformer.map_to_pixel(p) for p in polygon]
         xmin, ymin = np.min(polygon, axis=0)
         xmax, ymax = np.max(polygon, axis=0)
@@ -44,6 +42,19 @@
         class_ids.append(properties['class_id'])
         scores.append(properties.get('score', 1.0))
 
+    for feature in features:
+        geom_type = feature['geometry']['type']
+        coordinates = feature['geometry']['coordinates']
+        if geom_type == 'MultiPolygon':
+            for polygon in coordinates:
+                polygon_to_label(polygon[0], crs_transformer)
+        elif geom_type == 'Polygon':
+            polygon_to_label(coordinates[0], crs_transformer)
+        else:
+            raise Exception(
+                "Geometries of type {} are not supported in object detection \
+                labels.".format(geom_type))
+
     boxes = np.array([box.npbox_format() for box in boxes], dtype=float)
     class_ids = np.array(class_ids)
     scores = np.array(scores)

{"golden_diff": "diff --git a/src/rastervision/label_stores/object_detection_geojson_file.py b/src/rastervision/label_stores/object_detection_geojson_file.py\n--- a/src/rastervision/label_stores/object_detection_geojson_file.py\n+++ b/src/rastervision/label_stores/object_detection_geojson_file.py\n@@ -32,9 +32,7 @@\n     class_ids = []\n     scores = []\n \n-    for feature in features:\n-        # Convert polygon to pixel coords and then convert to bounding box.\n-        polygon = feature['geometry']['coordinates'][0]\n+    def polygon_to_label(polygon, crs_transformer):\n         polygon = [crs_transformer.map_to_pixel(p) for p in polygon]\n         xmin, ymin = np.min(polygon, axis=0)\n         xmax, ymax = np.max(polygon, axis=0)\n@@ -44,6 +42,19 @@\n         class_ids.append(properties['class_id'])\n         scores.append(properties.get('score', 1.0))\n \n+    for feature in features:\n+        geom_type = feature['geometry']['type']\n+        coordinates = feature['geometry']['coordinates']\n+        if geom_type == 'MultiPolygon':\n+            for polygon in coordinates:\n+                polygon_to_label(polygon[0], crs_transformer)\n+        elif geom_type == 'Polygon':\n+            polygon_to_label(coordinates[0], crs_transformer)\n+        else:\n+            raise Exception(\n+                \"Geometries of type {} are not supported in object detection \\\n+                labels.\".format(geom_type))\n+\n     boxes = np.array([box.npbox_format() for box in boxes], dtype=float)\n     class_ids = np.array(class_ids)\n     scores = np.array(scores)\n", "issue": "Add support for multipolygons\nEnable RV to handle geojson label stores that are encoded as multipolygons\n", "before_files": [{"content": "import json\n\nimport numpy as np\n\nfrom rastervision.core.box import Box\nfrom rastervision.labels.object_detection_labels import (ObjectDetectionLabels)\nfrom rastervision.label_stores.utils import (add_classes_to_geojson,\n                                             load_label_store_json)\nfrom rastervision.label_stores.object_detection_label_store import (\n    ObjectDetectionLabelStore)\nfrom rastervision.label_stores.utils import boxes_to_geojson\nfrom rastervision.utils.files import str_to_file, NotWritableError\n\n\ndef geojson_to_labels(geojson_dict, crs_transformer, extent=None):\n    \"\"\"Convert GeoJSON to ObjectDetectionLabels object.\n\n    If extent is provided, filter out the boxes that lie \"more than a little\n    bit\" outside the extent.\n\n    Args:\n        geojson_dict: dict in GeoJSON format\n        crs_transformer: used to convert map coords in geojson to pixel coords\n            in labels object\n        extent: Box in pixel coords\n\n    Returns:\n        ObjectDetectionLabels\n    \"\"\"\n    features = geojson_dict['features']\n    boxes = []\n    class_ids = []\n    scores = []\n\n    for feature in features:\n        # Convert polygon to pixel coords and then convert to bounding box.\n        polygon = feature['geometry']['coordinates'][0]\n        polygon = [crs_transformer.map_to_pixel(p) for p in polygon]\n        xmin, ymin = np.min(polygon, axis=0)\n        xmax, ymax = np.max(polygon, axis=0)\n        boxes.append(Box(ymin, xmin, ymax, xmax))\n\n        properties = feature['properties']\n        class_ids.append(properties['class_id'])\n        scores.append(properties.get('score', 1.0))\n\n    boxes = np.array([box.npbox_format() for box in boxes], dtype=float)\n    class_ids = np.array(class_ids)\n    scores = np.array(scores)\n\n    labels = ObjectDetectionLabels(boxes, class_ids, scores=scores)\n    if extent is not None:\n        labels = ObjectDetectionLabels.get_overlapping(\n            labels, extent, ioa_thresh=0.8, clip=True)\n    return labels\n\n\nclass ObjectDetectionGeoJSONFile(ObjectDetectionLabelStore):\n    def __init__(self,\n                 uri,\n                 crs_transformer,\n                 class_map,\n                 extent=None,\n                 readable=True,\n                 writable=False):\n        \"\"\"Construct ObjectDetectionLabelStore backed by a GeoJSON file.\n\n        Args:\n            uri: uri of GeoJSON file containing labels\n            crs_transformer: CRSTransformer to convert from map coords in label\n                in GeoJSON file to pixel coords.\n            class_map: ClassMap used to infer class_ids from class_name\n                (or label) field\n            extent: Box used to filter the labels by extent\n            readable: if True, expect the file to exist\n            writable: if True, allow writing to disk\n        \"\"\"\n        self.uri = uri\n        self.crs_transformer = crs_transformer\n        self.class_map = class_map\n        self.readable = readable\n        self.writable = writable\n\n        self.labels = ObjectDetectionLabels.make_empty()\n\n        json_dict = load_label_store_json(uri, readable)\n        if json_dict:\n            geojson = add_classes_to_geojson(json_dict, class_map)\n            self.labels = geojson_to_labels(\n                geojson, crs_transformer, extent=extent)\n\n    def save(self):\n        \"\"\"Save labels to URI if writable.\"\"\"\n        if self.writable:\n            boxes = self.labels.get_boxes()\n            class_ids = self.labels.get_class_ids().tolist()\n            scores = self.labels.get_scores().tolist()\n            geojson_dict = boxes_to_geojson(\n                boxes,\n                class_ids,\n                self.crs_transformer,\n                self.class_map,\n                scores=scores)\n            geojson_str = json.dumps(geojson_dict)\n            str_to_file(geojson_str, self.uri)\n        else:\n            raise NotWritableError('Cannot write with writable=False')\n", "path": "src/rastervision/label_stores/object_detection_geojson_file.py"}], "after_files": [{"content": "import json\n\nimport numpy as np\n\nfrom rastervision.core.box import Box\nfrom rastervision.labels.object_detection_labels import (ObjectDetectionLabels)\nfrom rastervision.label_stores.utils import (add_classes_to_geojson,\n                                             load_label_store_json)\nfrom rastervision.label_stores.object_detection_label_store import (\n    ObjectDetectionLabelStore)\nfrom rastervision.label_stores.utils import boxes_to_geojson\nfrom rastervision.utils.files import str_to_file, NotWritableError\n\n\ndef geojson_to_labels(geojson_dict, crs_transformer, extent=None):\n    \"\"\"Convert GeoJSON to ObjectDetectionLabels object.\n\n    If extent is provided, filter out the boxes that lie \"more than a little\n    bit\" outside the extent.\n\n    Args:\n        geojson_dict: dict in GeoJSON format\n        crs_transformer: used to convert map coords in geojson to pixel coords\n            in labels object\n        extent: Box in pixel coords\n\n    Returns:\n        ObjectDetectionLabels\n    \"\"\"\n    features = geojson_dict['features']\n    boxes = []\n    class_ids = []\n    scores = []\n\n    def polygon_to_label(polygon, crs_transformer):\n        polygon = [crs_transformer.map_to_pixel(p) for p in polygon]\n        xmin, ymin = np.min(polygon, axis=0)\n        xmax, ymax = np.max(polygon, axis=0)\n        boxes.append(Box(ymin, xmin, ymax, xmax))\n\n        properties = feature['properties']\n        class_ids.append(properties['class_id'])\n        scores.append(properties.get('score', 1.0))\n\n    for feature in features:\n        geom_type = feature['geometry']['type']\n        coordinates = feature['geometry']['coordinates']\n        if geom_type == 'MultiPolygon':\n            for polygon in coordinates:\n                polygon_to_label(polygon[0], crs_transformer)\n        elif geom_type == 'Polygon':\n            polygon_to_label(coordinates[0], crs_transformer)\n        else:\n            raise Exception(\n                \"Geometries of type {} are not supported in object detection \\\n                labels.\".format(geom_type))\n\n    boxes = np.array([box.npbox_format() for box in boxes], dtype=float)\n    class_ids = np.array(class_ids)\n    scores = np.array(scores)\n\n    labels = ObjectDetectionLabels(boxes, class_ids, scores=scores)\n    if extent is not None:\n        labels = ObjectDetectionLabels.get_overlapping(\n            labels, extent, ioa_thresh=0.8, clip=True)\n    return labels\n\n\nclass ObjectDetectionGeoJSONFile(ObjectDetectionLabelStore):\n    def __init__(self,\n                 uri,\n                 crs_transformer,\n                 class_map,\n                 extent=None,\n                 readable=True,\n                 writable=False):\n        \"\"\"Construct ObjectDetectionLabelStore backed by a GeoJSON file.\n\n        Args:\n            uri: uri of GeoJSON file containing labels\n            crs_transformer: CRSTransformer to convert from map coords in label\n                in GeoJSON file to pixel coords.\n            class_map: ClassMap used to infer class_ids from class_name\n                (or label) field\n            extent: Box used to filter the labels by extent\n            readable: if True, expect the file to exist\n            writable: if True, allow writing to disk\n        \"\"\"\n        self.uri = uri\n        self.crs_transformer = crs_transformer\n        self.class_map = class_map\n        self.readable = readable\n        self.writable = writable\n\n        self.labels = ObjectDetectionLabels.make_empty()\n\n        json_dict = load_label_store_json(uri, readable)\n        if json_dict:\n            geojson = add_classes_to_geojson(json_dict, class_map)\n            self.labels = geojson_to_labels(\n                geojson, crs_transformer, extent=extent)\n\n    def save(self):\n        \"\"\"Save labels to URI if writable.\"\"\"\n        if self.writable:\n            boxes = self.labels.get_boxes()\n            class_ids = self.labels.get_class_ids().tolist()\n            scores = self.labels.get_scores().tolist()\n            geojson_dict = boxes_to_geojson(\n                boxes,\n                class_ids,\n                self.crs_transformer,\n                self.class_map,\n                scores=scores)\n            geojson_str = json.dumps(geojson_dict)\n            str_to_file(geojson_str, self.uri)\n        else:\n            raise NotWritableError('Cannot write with writable=False')\n", "path": "src/rastervision/label_stores/object_detection_geojson_file.py"}]}