Skip to content

Commit 7dfd479

Browse files
committed
update GEOJSON location, add loading to migration
1 parent b886db0 commit 7dfd479

3 files changed

Lines changed: 67 additions & 5 deletions

File tree

.gitattributes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
client/package-lock.json linguist-generated=true
2-
bats_ai/data/species.geojson linguist-vendored=true
2+
bats_ai/core/data/species.geojson linguist-vendored=true
33
uv.lock linguist-generated=true
44
assets/example.wav filter=lfs diff=lfs merge=lfs -text
55
assets/model.mobilenet.onnx filter=lfs diff=lfs merge=lfs -text

bats_ai/core/management/commands/load_species_geojson.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from django.conf import settings
1515

16-
DEFAULT_GEOJSON = settings.BASE_DIR / "bats_ai/data/species.geojson"
16+
DEFAULT_GEOJSON = settings.BASE_DIR / "bats_ai/core/data/species.geojson"
1717

1818

1919
class Command(BaseCommand):

bats_ai/core/migrations/0036_rename_grts_cell_recording_sample_frame_id_and_more.py

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,62 @@
11
# Generated by Django 6.0.3 on 2026-04-08 13:29
22
from __future__ import annotations
33

4+
import json
5+
from pathlib import Path
6+
7+
from django.conf import settings
48
import django.contrib.gis.db.models.fields
9+
from django.contrib.gis.geos import GEOSGeometry
510
from django.db import migrations, models
611
import django.db.models.deletion
712

13+
DEFAULT_GEOJSON = settings.BASE_DIR / "bats_ai/core/data/species.geojson"
14+
15+
16+
def load_species_ranges_from_default_geojson(apps, schema_editor) -> None:
17+
Species = apps.get_model("core", "Species")
18+
SpeciesRange = apps.get_model("core", "SpeciesRange")
19+
20+
path = Path(DEFAULT_GEOJSON).resolve()
21+
if not path.is_file():
22+
raise FileNotFoundError(f"GeoJSON file not found: {path}")
23+
24+
doc = json.loads(path.read_text(encoding="utf-8"))
25+
if doc.get("type") != "FeatureCollection":
26+
raise ValueError('Expected a GeoJSON FeatureCollection ("type": "FeatureCollection").')
27+
28+
features = doc.get("features") or []
29+
for feature in features:
30+
props = feature.get("properties") or {}
31+
code = props.get("name")
32+
if not code or not str(code).strip():
33+
continue
34+
code = str(code).strip().upper()
35+
36+
geom_json = feature.get("geometry")
37+
if not geom_json:
38+
continue
39+
40+
geom = GEOSGeometry(json.dumps(geom_json))
41+
if geom.srid in (None, 0):
42+
geom.srid = 4326
43+
elif geom.srid != 4326:
44+
geom.transform(4326)
45+
46+
species = Species.objects.filter(species_code__iexact=code).first()
47+
if species is None:
48+
continue
49+
50+
fid = props.get("id")
51+
source_feature_id = str(fid) if fid is not None else ""
52+
SpeciesRange.objects.update_or_create(
53+
species=species,
54+
defaults={
55+
"geom": geom,
56+
"source_feature_id": source_feature_id,
57+
},
58+
)
59+
860

961
class Migration(migrations.Migration):
1062
dependencies = [
@@ -23,15 +75,21 @@ class Migration(migrations.Migration):
2375
(
2476
"id",
2577
models.BigAutoField(
26-
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
78+
auto_created=True,
79+
primary_key=True,
80+
serialize=False,
81+
verbose_name="ID",
2782
),
2883
),
29-
("geom", django.contrib.gis.db.models.fields.GeometryField(srid=4326)),
84+
(
85+
"geom",
86+
django.contrib.gis.db.models.fields.GeometryField(srid=4326),
87+
),
3088
(
3189
"source_feature_id",
3290
models.CharField(
3391
blank=True,
34-
help_text="Optional id from the source GeoJSON feature properties.",
92+
help_text=("Optional id from the source GeoJSON feature properties."),
3593
max_length=255,
3694
),
3795
),
@@ -45,4 +103,8 @@ class Migration(migrations.Migration):
45103
),
46104
],
47105
),
106+
migrations.RunPython(
107+
load_species_ranges_from_default_geojson,
108+
migrations.RunPython.noop,
109+
),
48110
]

0 commit comments

Comments
 (0)