We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add new overlap parameter in search filter
A user wants to be able to search for SpatialEntries that have x% overlap with the search geometry. We should add this as an additional field on the `SpatialEntryFilter`.

Perhaps call it `percent_overlap` and accept a number between 0 an 1.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `django-rgd/rgd/filters.py`
Content:
```
1 from django.contrib.gis import forms
2 from django.contrib.gis.db.models.functions import GeometryDistance
3 from django.contrib.gis.measure import D
4 from django.core.validators import RegexValidator
5 from django.db.models import F, Q
6 from django_filters import rest_framework as filters
7 from rgd.models import ChecksumFile, Collection, SpatialEntry
8 from rgd.permissions import get_paths
9 
10 
11 class GeometryFilter(filters.Filter):
12     field_class = forms.GeometryField
13     # Ensures GeoJSON objects are converted to correct SRID
14     field_class.widget.map_srid = 4326
15 
16 
17 class SpatialEntryFilter(filters.FilterSet):
18 
19     q = GeometryFilter(
20         help_text='A Well-known text (WKT) representation of a geometry or a GeoJSON.',
21         label='WKT/GeoJSON',
22         method='filter_q',
23     )
24     predicate = filters.ChoiceFilter(
25         choices=(
26             ('contains', 'contains'),
27             ('crosses', 'crosses'),
28             ('disjoint', 'disjoint'),
29             ('equals', 'equals'),
30             ('intersects', 'intersects'),
31             ('overlaps', 'overlaps'),
32             ('touches', 'touches'),
33             ('within', 'within'),
34         ),
35         help_text=(
36             'A named spatial predicate based on the DE-9IM. This spatial predicate will be used '
37             'to filter data such that `predicate(a, b)` where `b` is the queried geometry.'
38         ),
39         label='Spatial predicate',
40         method='filter_predicate',
41     )
42     relates = filters.CharFilter(
43         help_text=(
44             'Specify exactly how the queried geometry should relate to the data using a DE-9IM '
45             'string code.'
46         ),
47         label='DE-9IM string code',
48         max_length=9,
49         method='filter_relates',
50         min_length=9,
51         validators=(
52             RegexValidator(regex=r'^[\*012TF]{9}$', message='Enter a valid DE-9IM string code.'),
53         ),
54     )
55     distance = filters.RangeFilter(
56         help_text='The minimum/maximum distance around the queried geometry in meters.',
57         label='Distance',
58         method='filter_distance',
59     )
60     acquired = filters.IsoDateTimeFromToRangeFilter(
61         field_name='acquisition_date',
62         help_text='The ISO 8601 formatted date and time when data was acquired.',
63         label='Acquired',
64     )
65     instrumentation = filters.CharFilter(
66         field_name='instrumentation',
67         help_text='The instrumentation used to acquire at least one of these data.',
68         label='Instrumentation',
69         lookup_expr='icontains',
70     )
71     time_of_day = filters.TimeRangeFilter(
72         help_text='The minimum/maximum times during the day the records were acquired.',
73         label='Time of Day',
74         method='filter_time_of_day',
75     )
76     collections = filters.ModelMultipleChoiceFilter(
77         help_text='One or more collections that the data might belong to.',
78         label='Collections',
79         method='filter_collection',
80         queryset=Collection.objects.all(),
81     )
82 
83     @property
84     def _geometry(self):
85         return self.form.cleaned_data['q']
86 
87     @property
88     def _has_geom(self):
89         return self._geometry is not None
90 
91     def filter_q(self, queryset, name, value):
92         """Sort the queryset by distance to queried geometry.
93 
94         Annotates the queryset with `distance`.
95 
96         This uses the efficient KNN operation:
97         https://postgis.net/docs/geometry_distance_knn.html
98         """
99         if value:
100             queryset = queryset.annotate(distance=GeometryDistance('footprint', value)).order_by(
101                 'distance'
102             )
103         return queryset
104 
105     def filter_predicate(self, queryset, name, value):
106         """Filter the spatial entries by the chosen predicate."""
107         if value and self._has_geom:
108             queryset = queryset.filter(**{f'footprint__{value}': self._geometry})
109         return queryset
110 
111     def filter_relates(self, queryset, name, value):
112         """Filter the spatial entries by the chosen DE-9IM."""
113         if value and self._has_geom:
114             queryset = queryset.filter(footprint__relates=(self._geometry, value))
115         return queryset
116 
117     def filter_distance(self, queryset, name, value):
118         """Filter the queryset by distance to the queried geometry.
119 
120         We may wish to use the distance in degrees later on. This is
121         very taxing on the DBMS right now. The distance in degrees
122         can be provided by the initial geometry query.
123         """
124         if value and self._has_geom:
125             geom = self._geometry
126             if value.start is not None:
127                 queryset = queryset.filter(footprint__distance_gte=(geom, D(m=value.start)))
128             if value.stop is not None:
129                 queryset = queryset.filter(footprint__distance_lte=(geom, D(m=value.stop)))
130         return queryset
131 
132     def filter_time_of_day(self, queryset, name, value):
133         """Filter the queryset by time of day acquired.
134 
135         Use case: find all rasters acquired between 8am and 4pm
136         for all days in the acquired date range (i.e. only daytime imagery)
137         """
138         if value is not None:
139             queryset = queryset.annotate(time_of_day=F('acquisition_date__time'))
140             if value.start is not None:
141                 queryset = queryset.filter(time_of_day__gte=value.start)
142             if value.stop is not None:
143                 queryset = queryset.filter(time_of_day__lte=value.stop)
144         return queryset
145 
146     def filter_collection(self, queryset, name, value):
147         """Filter the queryset by the collection it belongs to."""
148         if value:
149             conditions = Q()
150             for path in get_paths(queryset.model, ChecksumFile):
151                 conditions |= path.q(collection__in=value)
152             return queryset.filter(conditions).distinct()
153         return queryset
154 
155     class Meta:
156         model = SpatialEntry
157         fields = [
158             'q',
159             'predicate',
160             'relates',
161             'distance',
162             'acquired',
163             'instrumentation',
164             'time_of_day',
165             'collections',
166         ]
167 
168 
169 class CollectionFilter(filters.FilterSet):
170     name = filters.CharFilter(
171         field_name='name',
172         help_text='The name of the Collection.',
173         label='Name',
174         lookup_expr='exact',
175     )
176 
177     class Meta:
178         model = Collection
179         fields = [
180             'name',
181         ]
182
```
--- 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/django-rgd/rgd/filters.py b/django-rgd/rgd/filters.py
--- a/django-rgd/rgd/filters.py
+++ b/django-rgd/rgd/filters.py
@@ -1,8 +1,9 @@
 from django.contrib.gis import forms
-from django.contrib.gis.db.models.functions import GeometryDistance
+from django.contrib.gis.db.models.functions import Area, GeometryDistance, Intersection
 from django.contrib.gis.measure import D
 from django.core.validators import RegexValidator
-from django.db.models import F, Q
+from django.db.models import F, FloatField, Q
+from django.db.models.functions import Cast
 from django_filters import rest_framework as filters
 from rgd.models import ChecksumFile, Collection, SpatialEntry
 from rgd.permissions import get_paths
@@ -79,6 +80,11 @@
         method='filter_collection',
         queryset=Collection.objects.all(),
     )
+    percent_overlap = filters.NumberFilter(
+        help_text='The minute percent overlap with search geometry (between 0 and 1).',
+        label='Percent overlap',
+        method='filter_percent_overlap',
+    )
 
     @property
     def _geometry(self):
@@ -152,6 +158,18 @@
             return queryset.filter(conditions).distinct()
         return queryset
 
+    def filter_percent_overlap(self, queryset, name, value: float):
+        """Filter the queryset by percent overlap with the queried geometry."""
+        if value is not None and value > 0 and value <= 1 and self._has_geom:
+            geom = self._geometry
+            queryset = queryset.filter(footprint__overlaps=geom).annotate(
+                overlap_percentage=(
+                    Cast(Area(Intersection(F('footprint'), geom)) / Area(geom), FloatField())
+                )
+            )
+            queryset = queryset.filter(overlap_percentage__gte=value)
+        return queryset
+
     class Meta:
         model = SpatialEntry
         fields = [
@@ -160,6 +178,7 @@
             'relates',
             'distance',
             'acquired',
+            'percent_overlap',
             'instrumentation',
             'time_of_day',
             'collections',

{"golden_diff": "diff --git a/django-rgd/rgd/filters.py b/django-rgd/rgd/filters.py\n--- a/django-rgd/rgd/filters.py\n+++ b/django-rgd/rgd/filters.py\n@@ -1,8 +1,9 @@\n from django.contrib.gis import forms\n-from django.contrib.gis.db.models.functions import GeometryDistance\n+from django.contrib.gis.db.models.functions import Area, GeometryDistance, Intersection\n from django.contrib.gis.measure import D\n from django.core.validators import RegexValidator\n-from django.db.models import F, Q\n+from django.db.models import F, FloatField, Q\n+from django.db.models.functions import Cast\n from django_filters import rest_framework as filters\n from rgd.models import ChecksumFile, Collection, SpatialEntry\n from rgd.permissions import get_paths\n@@ -79,6 +80,11 @@\n         method='filter_collection',\n         queryset=Collection.objects.all(),\n     )\n+    percent_overlap = filters.NumberFilter(\n+        help_text='The minute percent overlap with search geometry (between 0 and 1).',\n+        label='Percent overlap',\n+        method='filter_percent_overlap',\n+    )\n \n     @property\n     def _geometry(self):\n@@ -152,6 +158,18 @@\n             return queryset.filter(conditions).distinct()\n         return queryset\n \n+    def filter_percent_overlap(self, queryset, name, value: float):\n+        \"\"\"Filter the queryset by percent overlap with the queried geometry.\"\"\"\n+        if value is not None and value > 0 and value <= 1 and self._has_geom:\n+            geom = self._geometry\n+            queryset = queryset.filter(footprint__overlaps=geom).annotate(\n+                overlap_percentage=(\n+                    Cast(Area(Intersection(F('footprint'), geom)) / Area(geom), FloatField())\n+                )\n+            )\n+            queryset = queryset.filter(overlap_percentage__gte=value)\n+        return queryset\n+\n     class Meta:\n         model = SpatialEntry\n         fields = [\n@@ -160,6 +178,7 @@\n             'relates',\n             'distance',\n             'acquired',\n+            'percent_overlap',\n             'instrumentation',\n             'time_of_day',\n             'collections',\n", "issue": "Add new overlap parameter in search filter\nA user wants to be able to search for SpatialEntries that have x% overlap with the search geometry. We should add this as an additional field on the `SpatialEntryFilter`.\r\n\r\nPerhaps call it `percent_overlap` and accept a number between 0 an 1.\n", "before_files": [{"content": "from django.contrib.gis import forms\nfrom django.contrib.gis.db.models.functions import GeometryDistance\nfrom django.contrib.gis.measure import D\nfrom django.core.validators import RegexValidator\nfrom django.db.models import F, Q\nfrom django_filters import rest_framework as filters\nfrom rgd.models import ChecksumFile, Collection, SpatialEntry\nfrom rgd.permissions import get_paths\n\n\nclass GeometryFilter(filters.Filter):\n    field_class = forms.GeometryField\n    # Ensures GeoJSON objects are converted to correct SRID\n    field_class.widget.map_srid = 4326\n\n\nclass SpatialEntryFilter(filters.FilterSet):\n\n    q = GeometryFilter(\n        help_text='A Well-known text (WKT) representation of a geometry or a GeoJSON.',\n        label='WKT/GeoJSON',\n        method='filter_q',\n    )\n    predicate = filters.ChoiceFilter(\n        choices=(\n            ('contains', 'contains'),\n            ('crosses', 'crosses'),\n            ('disjoint', 'disjoint'),\n            ('equals', 'equals'),\n            ('intersects', 'intersects'),\n            ('overlaps', 'overlaps'),\n            ('touches', 'touches'),\n            ('within', 'within'),\n        ),\n        help_text=(\n            'A named spatial predicate based on the DE-9IM. This spatial predicate will be used '\n            'to filter data such that `predicate(a, b)` where `b` is the queried geometry.'\n        ),\n        label='Spatial predicate',\n        method='filter_predicate',\n    )\n    relates = filters.CharFilter(\n        help_text=(\n            'Specify exactly how the queried geometry should relate to the data using a DE-9IM '\n            'string code.'\n        ),\n        label='DE-9IM string code',\n        max_length=9,\n        method='filter_relates',\n        min_length=9,\n        validators=(\n            RegexValidator(regex=r'^[\\*012TF]{9}$', message='Enter a valid DE-9IM string code.'),\n        ),\n    )\n    distance = filters.RangeFilter(\n        help_text='The minimum/maximum distance around the queried geometry in meters.',\n        label='Distance',\n        method='filter_distance',\n    )\n    acquired = filters.IsoDateTimeFromToRangeFilter(\n        field_name='acquisition_date',\n        help_text='The ISO 8601 formatted date and time when data was acquired.',\n        label='Acquired',\n    )\n    instrumentation = filters.CharFilter(\n        field_name='instrumentation',\n        help_text='The instrumentation used to acquire at least one of these data.',\n        label='Instrumentation',\n        lookup_expr='icontains',\n    )\n    time_of_day = filters.TimeRangeFilter(\n        help_text='The minimum/maximum times during the day the records were acquired.',\n        label='Time of Day',\n        method='filter_time_of_day',\n    )\n    collections = filters.ModelMultipleChoiceFilter(\n        help_text='One or more collections that the data might belong to.',\n        label='Collections',\n        method='filter_collection',\n        queryset=Collection.objects.all(),\n    )\n\n    @property\n    def _geometry(self):\n        return self.form.cleaned_data['q']\n\n    @property\n    def _has_geom(self):\n        return self._geometry is not None\n\n    def filter_q(self, queryset, name, value):\n        \"\"\"Sort the queryset by distance to queried geometry.\n\n        Annotates the queryset with `distance`.\n\n        This uses the efficient KNN operation:\n        https://postgis.net/docs/geometry_distance_knn.html\n        \"\"\"\n        if value:\n            queryset = queryset.annotate(distance=GeometryDistance('footprint', value)).order_by(\n                'distance'\n            )\n        return queryset\n\n    def filter_predicate(self, queryset, name, value):\n        \"\"\"Filter the spatial entries by the chosen predicate.\"\"\"\n        if value and self._has_geom:\n            queryset = queryset.filter(**{f'footprint__{value}': self._geometry})\n        return queryset\n\n    def filter_relates(self, queryset, name, value):\n        \"\"\"Filter the spatial entries by the chosen DE-9IM.\"\"\"\n        if value and self._has_geom:\n            queryset = queryset.filter(footprint__relates=(self._geometry, value))\n        return queryset\n\n    def filter_distance(self, queryset, name, value):\n        \"\"\"Filter the queryset by distance to the queried geometry.\n\n        We may wish to use the distance in degrees later on. This is\n        very taxing on the DBMS right now. The distance in degrees\n        can be provided by the initial geometry query.\n        \"\"\"\n        if value and self._has_geom:\n            geom = self._geometry\n            if value.start is not None:\n                queryset = queryset.filter(footprint__distance_gte=(geom, D(m=value.start)))\n            if value.stop is not None:\n                queryset = queryset.filter(footprint__distance_lte=(geom, D(m=value.stop)))\n        return queryset\n\n    def filter_time_of_day(self, queryset, name, value):\n        \"\"\"Filter the queryset by time of day acquired.\n\n        Use case: find all rasters acquired between 8am and 4pm\n        for all days in the acquired date range (i.e. only daytime imagery)\n        \"\"\"\n        if value is not None:\n            queryset = queryset.annotate(time_of_day=F('acquisition_date__time'))\n            if value.start is not None:\n                queryset = queryset.filter(time_of_day__gte=value.start)\n            if value.stop is not None:\n                queryset = queryset.filter(time_of_day__lte=value.stop)\n        return queryset\n\n    def filter_collection(self, queryset, name, value):\n        \"\"\"Filter the queryset by the collection it belongs to.\"\"\"\n        if value:\n            conditions = Q()\n            for path in get_paths(queryset.model, ChecksumFile):\n                conditions |= path.q(collection__in=value)\n            return queryset.filter(conditions).distinct()\n        return queryset\n\n    class Meta:\n        model = SpatialEntry\n        fields = [\n            'q',\n            'predicate',\n            'relates',\n            'distance',\n            'acquired',\n            'instrumentation',\n            'time_of_day',\n            'collections',\n        ]\n\n\nclass CollectionFilter(filters.FilterSet):\n    name = filters.CharFilter(\n        field_name='name',\n        help_text='The name of the Collection.',\n        label='Name',\n        lookup_expr='exact',\n    )\n\n    class Meta:\n        model = Collection\n        fields = [\n            'name',\n        ]\n", "path": "django-rgd/rgd/filters.py"}], "after_files": [{"content": "from django.contrib.gis import forms\nfrom django.contrib.gis.db.models.functions import Area, GeometryDistance, Intersection\nfrom django.contrib.gis.measure import D\nfrom django.core.validators import RegexValidator\nfrom django.db.models import F, FloatField, Q\nfrom django.db.models.functions import Cast\nfrom django_filters import rest_framework as filters\nfrom rgd.models import ChecksumFile, Collection, SpatialEntry\nfrom rgd.permissions import get_paths\n\n\nclass GeometryFilter(filters.Filter):\n    field_class = forms.GeometryField\n    # Ensures GeoJSON objects are converted to correct SRID\n    field_class.widget.map_srid = 4326\n\n\nclass SpatialEntryFilter(filters.FilterSet):\n\n    q = GeometryFilter(\n        help_text='A Well-known text (WKT) representation of a geometry or a GeoJSON.',\n        label='WKT/GeoJSON',\n        method='filter_q',\n    )\n    predicate = filters.ChoiceFilter(\n        choices=(\n            ('contains', 'contains'),\n            ('crosses', 'crosses'),\n            ('disjoint', 'disjoint'),\n            ('equals', 'equals'),\n            ('intersects', 'intersects'),\n            ('overlaps', 'overlaps'),\n            ('touches', 'touches'),\n            ('within', 'within'),\n        ),\n        help_text=(\n            'A named spatial predicate based on the DE-9IM. This spatial predicate will be used '\n            'to filter data such that `predicate(a, b)` where `b` is the queried geometry.'\n        ),\n        label='Spatial predicate',\n        method='filter_predicate',\n    )\n    relates = filters.CharFilter(\n        help_text=(\n            'Specify exactly how the queried geometry should relate to the data using a DE-9IM '\n            'string code.'\n        ),\n        label='DE-9IM string code',\n        max_length=9,\n        method='filter_relates',\n        min_length=9,\n        validators=(\n            RegexValidator(regex=r'^[\\*012TF]{9}$', message='Enter a valid DE-9IM string code.'),\n        ),\n    )\n    distance = filters.RangeFilter(\n        help_text='The minimum/maximum distance around the queried geometry in meters.',\n        label='Distance',\n        method='filter_distance',\n    )\n    acquired = filters.IsoDateTimeFromToRangeFilter(\n        field_name='acquisition_date',\n        help_text='The ISO 8601 formatted date and time when data was acquired.',\n        label='Acquired',\n    )\n    instrumentation = filters.CharFilter(\n        field_name='instrumentation',\n        help_text='The instrumentation used to acquire at least one of these data.',\n        label='Instrumentation',\n        lookup_expr='icontains',\n    )\n    time_of_day = filters.TimeRangeFilter(\n        help_text='The minimum/maximum times during the day the records were acquired.',\n        label='Time of Day',\n        method='filter_time_of_day',\n    )\n    collections = filters.ModelMultipleChoiceFilter(\n        help_text='One or more collections that the data might belong to.',\n        label='Collections',\n        method='filter_collection',\n        queryset=Collection.objects.all(),\n    )\n    percent_overlap = filters.NumberFilter(\n        help_text='The minute percent overlap with search geometry (between 0 and 1).',\n        label='Percent overlap',\n        method='filter_percent_overlap',\n    )\n\n    @property\n    def _geometry(self):\n        return self.form.cleaned_data['q']\n\n    @property\n    def _has_geom(self):\n        return self._geometry is not None\n\n    def filter_q(self, queryset, name, value):\n        \"\"\"Sort the queryset by distance to queried geometry.\n\n        Annotates the queryset with `distance`.\n\n        This uses the efficient KNN operation:\n        https://postgis.net/docs/geometry_distance_knn.html\n        \"\"\"\n        if value:\n            queryset = queryset.annotate(distance=GeometryDistance('footprint', value)).order_by(\n                'distance'\n            )\n        return queryset\n\n    def filter_predicate(self, queryset, name, value):\n        \"\"\"Filter the spatial entries by the chosen predicate.\"\"\"\n        if value and self._has_geom:\n            queryset = queryset.filter(**{f'footprint__{value}': self._geometry})\n        return queryset\n\n    def filter_relates(self, queryset, name, value):\n        \"\"\"Filter the spatial entries by the chosen DE-9IM.\"\"\"\n        if value and self._has_geom:\n            queryset = queryset.filter(footprint__relates=(self._geometry, value))\n        return queryset\n\n    def filter_distance(self, queryset, name, value):\n        \"\"\"Filter the queryset by distance to the queried geometry.\n\n        We may wish to use the distance in degrees later on. This is\n        very taxing on the DBMS right now. The distance in degrees\n        can be provided by the initial geometry query.\n        \"\"\"\n        if value and self._has_geom:\n            geom = self._geometry\n            if value.start is not None:\n                queryset = queryset.filter(footprint__distance_gte=(geom, D(m=value.start)))\n            if value.stop is not None:\n                queryset = queryset.filter(footprint__distance_lte=(geom, D(m=value.stop)))\n        return queryset\n\n    def filter_time_of_day(self, queryset, name, value):\n        \"\"\"Filter the queryset by time of day acquired.\n\n        Use case: find all rasters acquired between 8am and 4pm\n        for all days in the acquired date range (i.e. only daytime imagery)\n        \"\"\"\n        if value is not None:\n            queryset = queryset.annotate(time_of_day=F('acquisition_date__time'))\n            if value.start is not None:\n                queryset = queryset.filter(time_of_day__gte=value.start)\n            if value.stop is not None:\n                queryset = queryset.filter(time_of_day__lte=value.stop)\n        return queryset\n\n    def filter_collection(self, queryset, name, value):\n        \"\"\"Filter the queryset by the collection it belongs to.\"\"\"\n        if value:\n            conditions = Q()\n            for path in get_paths(queryset.model, ChecksumFile):\n                conditions |= path.q(collection__in=value)\n            return queryset.filter(conditions).distinct()\n        return queryset\n\n    def filter_percent_overlap(self, queryset, name, value: float):\n        \"\"\"Filter the queryset by percent overlap with the queried geometry.\"\"\"\n        if value is not None and value > 0 and value <= 1 and self._has_geom:\n            geom = self._geometry\n            queryset = queryset.filter(footprint__overlaps=geom).annotate(\n                overlap_percentage=(\n                    Cast(Area(Intersection(F('footprint'), geom)) / Area(geom), FloatField())\n                )\n            )\n            queryset = queryset.filter(overlap_percentage__gte=value)\n        return queryset\n\n    class Meta:\n        model = SpatialEntry\n        fields = [\n            'q',\n            'predicate',\n            'relates',\n            'distance',\n            'acquired',\n            'percent_overlap',\n            'instrumentation',\n            'time_of_day',\n            'collections',\n        ]\n\n\nclass CollectionFilter(filters.FilterSet):\n    name = filters.CharFilter(\n        field_name='name',\n        help_text='The name of the Collection.',\n        label='Name',\n        lookup_expr='exact',\n    )\n\n    class Meta:\n        model = Collection\n        fields = [\n            'name',\n        ]\n", "path": "django-rgd/rgd/filters.py"}]}