From d788d841f8dcb3344e8660baa6a5f97e2c9ae8a2 Mon Sep 17 00:00:00 2001 From: Ed Chalstrey Date: Fri, 6 Sep 2024 10:26:43 +0100 Subject: [PATCH 1/5] update docs page --- docs/source/admin/setup/spatialdb.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/admin/setup/spatialdb.rst b/docs/source/admin/setup/spatialdb.rst index 9b7b6906f..a3550a068 100644 --- a/docs/source/admin/setup/spatialdb.rst +++ b/docs/source/admin/setup/spatialdb.rst @@ -12,11 +12,11 @@ Cliopatria shape dataset This will create a new file with the name "cliopatria_seshat_processed.geojson". Note: You can preview the file in the Jupyter notebook found in the `notebooks` directory. Instructions on how to run the notebook are found in the `README.md` file in the same directory. -5. Go back to the Seshat repo on the machine the website code is running from (if you are running it on a remote server, upload the processed GeoJSON). With your Seshat Python environment activated, you can populate ``core_videoshapefile`` table using the following command: +5. Go back to the Seshat repo on the machine the website code is running from (if you are running it on a remote server, upload the processed GeoJSON). With your Seshat Python environment activated, you can populate ``core_cliopatria`` table using the following command: .. code-block:: bash - $ python manage.py populate_videodata /path/to/cliopatria_seshat_processed.geojson + $ python manage.py populate_cliopatria /path/to/cliopatria_seshat_processed.geojson GADM From 8d9dbd6dda3394a4bc9f2b8932c70ec5bacf3403 Mon Sep 17 00:00:00 2001 From: Ed Chalstrey Date: Fri, 6 Sep 2024 10:26:50 +0100 Subject: [PATCH 2/5] update form --- seshat/apps/core/forms.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/seshat/apps/core/forms.py b/seshat/apps/core/forms.py index c64521b8e..0b2f6b3ba 100644 --- a/seshat/apps/core/forms.py +++ b/seshat/apps/core/forms.py @@ -130,7 +130,7 @@ class Meta: 'end_year': 'End Year', 'home_seshat_region': 'Home Seshat Region', 'polity_tag': 'Polity Tag', - 'shapefile_name': 'Shapefile name', + 'shapefile_name': 'Shapefile ID', 'private_comment': 'Private Comment (optional)', 'general_description': 'General Description of the Polity', @@ -149,7 +149,7 @@ class Meta: 'home_seshat_region': forms.Select(attrs={'class': 'form-control js-example-basic-single form-select mb-3',}), 'polity_tag': forms.Select(attrs={'class': 'form-control form-select mb-3',}), 'shapefile_name': forms.TextInput(attrs={'class': 'form-control mb-3', }), - 'private_comment': forms.Textarea(attrs={'class': 'form-control', 'style': 'height: 100px', 'placeholder':'Add a private comment that will only be visible to Seshat experts and RAs.\nUse this box to request edits to the polity map data.'}), + 'private_comment': forms.Textarea(attrs={'class': 'form-control', 'style': 'height: 100px', 'placeholder':'Add a private comment that will only be visible to Seshat experts and RAs.\nUse this box to request edits to the polity border shapes. Enter the ID of the relevant shape in the box above (found by clicking on the map).'}), 'general_description': forms.Textarea(attrs={'class': 'form-control mb-3', 'style': 'height: 265px', 'placeholder':'Add a general description (optional)'}), } @@ -171,7 +171,7 @@ class Meta: 'start_year': 'Start Year', 'end_year': 'End Year', 'home_seshat_region': 'Home Seshat Region', - 'shapefile_name': 'Shapefile name', + 'shapefile_name': 'Shapefile ID', 'polity_tag': 'Polity Tag', 'private_comment': 'Private Comment (optional)', 'general_description': 'General Description of the Polity', @@ -191,7 +191,7 @@ class Meta: 'home_seshat_region': forms.Select(attrs={'class': 'form-control js-example-basic-single form-select mb-3',}), 'polity_tag': forms.Select(attrs={'class': 'form-control form-select mb-3',}), 'shapefile_name': forms.TextInput(attrs={'class': 'form-control mb-3', }), - 'private_comment': forms.Textarea(attrs={'class': 'form-control', 'style': 'height: 100px', 'placeholder':'Add a private comment that will only be visible to seshat experts and RAs.\nUse this box to request edits to the polity map data.'}), + 'private_comment': forms.Textarea(attrs={'class': 'form-control', 'style': 'height: 100px', 'placeholder':'Add a private comment that will only be visible to Seshat experts and RAs.\nUse this box to request edits to the polity border shapes. Enter the ID of the relevant shape in the box above (found by clicking on the map).'}), 'general_description': forms.Textarea(attrs={'class': 'form-control mb-3', 'style': 'height: 265px', 'placeholder':'Add a general description (optional)'}), } From 5e8cbacc96816c5be071c52301a1a25a9429531d Mon Sep 17 00:00:00 2001 From: Ed Chalstrey Date: Fri, 6 Sep 2024 10:30:10 +0100 Subject: [PATCH 3/5] update command script --- ...te_videodata.py => populate_cliopatria.py} | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) rename seshat/apps/core/management/commands/{populate_videodata.py => populate_cliopatria.py} (83%) diff --git a/seshat/apps/core/management/commands/populate_videodata.py b/seshat/apps/core/management/commands/populate_cliopatria.py similarity index 83% rename from seshat/apps/core/management/commands/populate_videodata.py rename to seshat/apps/core/management/commands/populate_cliopatria.py index 9a7754399..ae8e86ea0 100644 --- a/seshat/apps/core/management/commands/populate_videodata.py +++ b/seshat/apps/core/management/commands/populate_cliopatria.py @@ -3,7 +3,7 @@ from django.contrib.gis.geos import GEOSGeometry, MultiPolygon from django.core.management.base import BaseCommand from django.db import connection -from seshat.apps.core.models import VideoShapefile +from seshat.apps.core.models import Cliopatria class Command(BaseCommand): @@ -30,23 +30,23 @@ def handle(self, *args, **options): cliopatria_data = json.load(f) self.stdout.write(self.style.SUCCESS(f"Successfully loaded Cliopatria shape dataset from {cliopatria_geojson_path}")) - # Clear the VideoShapefile table - self.stdout.write(self.style.SUCCESS('Clearing VideoShapefile table...')) - VideoShapefile.objects.all().delete() - self.stdout.write(self.style.SUCCESS('VideoShapefile table cleared')) + # Clear the Cliopatria table + self.stdout.write(self.style.SUCCESS('Clearing Cliopatria table...')) + Cliopatria.objects.all().delete() + self.stdout.write(self.style.SUCCESS('Cliopatria table cleared')) - # Iterate through the data and create VideoShapefile instances + # Iterate through the data and create Cliopatria instances self.stdout.write(self.style.SUCCESS('Adding data to the database...')) for feature in cliopatria_data['features']: properties = feature['properties'] - self.stdout.write(self.style.SUCCESS(f"Creating VideoShapefile instance for {properties['DisplayName']} ({properties['FromYear']} - {properties['ToYear']})")) + self.stdout.write(self.style.SUCCESS(f"Creating Cliopatria instance for {properties['DisplayName']} ({properties['FromYear']} - {properties['ToYear']})")) # Save geom and convert Polygon to MultiPolygon if necessary geom = GEOSGeometry(json.dumps(feature['geometry'])) if geom.geom_type == 'Polygon': geom = MultiPolygon(geom) - VideoShapefile.objects.create( + Cliopatria.objects.create( geom=geom, name=properties['DisplayName'], wikipedia_name=properties['Wikipedia'], @@ -72,14 +72,14 @@ def handle(self, *args, **options): ## Use this code if you want to simplify the geometries # with connection.cursor() as cursor: # cursor.execute(""" - # UPDATE core_videoshapefile + # UPDATE core_cliopatria # SET simplified_geom = ST_Simplify(geom, 0.07); # """) ## Use this code if you don't need to simplify the geometries with connection.cursor() as cursor: cursor.execute(""" - UPDATE core_videoshapefile + UPDATE core_cliopatria SET simplified_geom = geom; """) self.stdout.write(self.style.SUCCESS('Simplified geometries added')) From fe3dc4b4c6dc849284522aaf4df81cfe1e6f7e88 Mon Sep 17 00:00:00 2001 From: Ed Chalstrey Date: Fri, 6 Sep 2024 10:37:49 +0100 Subject: [PATCH 4/5] rename model and api bits --- .../0068_rename_videoshapefile_cliopatria.py | 17 +++++++++++++++++ seshat/apps/core/models.py | 2 +- seshat/apps/core/tests/tests.py | 10 +++++----- seshat/apps/core/views.py | 18 +++++++++--------- seshat/apps/seshat_api/filters/core.py | 6 +++--- seshat/apps/seshat_api/models.py | 4 ++-- seshat/apps/seshat_api/urls.py | 4 ++-- seshat/apps/seshat_api/views/core.py | 10 +++++----- 8 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 seshat/apps/core/migrations/0068_rename_videoshapefile_cliopatria.py diff --git a/seshat/apps/core/migrations/0068_rename_videoshapefile_cliopatria.py b/seshat/apps/core/migrations/0068_rename_videoshapefile_cliopatria.py new file mode 100644 index 000000000..4e9959f05 --- /dev/null +++ b/seshat/apps/core/migrations/0068_rename_videoshapefile_cliopatria.py @@ -0,0 +1,17 @@ +# Generated by Django 4.0.3 on 2024-09-06 09:37 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0067_reference_item_type_seshatprivatecommentpart_is_done_and_more'), + ] + + operations = [ + migrations.RenameModel( + old_name='VideoShapefile', + new_name='Cliopatria', + ), + ] diff --git a/seshat/apps/core/models.py b/seshat/apps/core/models.py index 827d31e8d..14791bb76 100644 --- a/seshat/apps/core/models.py +++ b/seshat/apps/core/models.py @@ -1129,7 +1129,7 @@ def __str__(self) -> str: # Shapefile models -class VideoShapefile(models.Model): +class Cliopatria(models.Model): """ Model representing Cliopatria polity borders dataset. """ diff --git a/seshat/apps/core/tests/tests.py b/seshat/apps/core/tests/tests.py index 3a424e876..c861c97b4 100644 --- a/seshat/apps/core/tests/tests.py +++ b/seshat/apps/core/tests/tests.py @@ -2,7 +2,7 @@ from django.contrib.gis.geos import MultiPolygon, Polygon, GEOSGeometry from django.test import TestCase, Client from django.urls import reverse -from ..models import VideoShapefile, GADMShapefile, GADMCountries, GADMProvinces, Polity, Capital +from ..models import Cliopatria, GADMShapefile, GADMCountries, GADMProvinces, Polity, Capital from ...general.models import Polity_capital, Polity_peak_years, Polity_language, Polity_religious_tradition from ...sc.models import Judge from ...rt.models import Gov_res_pub_pros @@ -44,7 +44,7 @@ def setUp(self): start_year=-100, end_year=1100 ) - self.video_shapefile = VideoShapefile.objects.create( + self.video_shapefile = Cliopatria.objects.create( id=1, geom=self.square, simplified_geom=self.square, @@ -60,7 +60,7 @@ def setUp(self): member_of="Test member_of", wikipedia_name="Test Wikipedia" ) - VideoShapefile.objects.create( + Cliopatria.objects.create( id=2, geom=self.square, simplified_geom=self.square, @@ -172,8 +172,8 @@ def setUp(self): # Model tests def test_video_shapefile_creation(self): - """Test the creation of a VideoShapefile instance.""" - self.assertIsInstance(self.video_shapefile, VideoShapefile) + """Test the creation of a Cliopatria instance.""" + self.assertIsInstance(self.video_shapefile, Cliopatria) self.assertEqual(self.video_shapefile.name, "Testpolityname") def test_gadm_shapefile_creation(self): diff --git a/seshat/apps/core/views.py b/seshat/apps/core/views.py index 72896f830..c3a1a3ea5 100644 --- a/seshat/apps/core/views.py +++ b/seshat/apps/core/views.py @@ -65,7 +65,7 @@ from ..crisisdb.models import Power_transition -from .models import Citation, Polity, Section, Subsection, Variablehierarchy, Reference, SeshatComment, SeshatCommentPart, Nga, Ngapolityrel, Capital, Seshat_region, Macro_region, VideoShapefile, GADMCountries, GADMProvinces, SeshatCommon, ScpThroughCtn, SeshatPrivateComment, SeshatPrivateCommentPart, Religion +from .models import Citation, Polity, Section, Subsection, Variablehierarchy, Reference, SeshatComment, SeshatCommentPart, Nga, Ngapolityrel, Capital, Seshat_region, Macro_region, Cliopatria, GADMCountries, GADMProvinces, SeshatCommon, ScpThroughCtn, SeshatPrivateComment, SeshatPrivateCommentPart, Religion import pprint import requests from requests.structures import CaseInsensitiveDict @@ -3873,7 +3873,7 @@ def get_polity_shape_content(displayed_year="all", seshat_id="all", tick_number= Only one of displayed_year or seshat_id should be set; not both. Note: - seshat_id in VideoShapefile is new_name in Polity. + seshat_id in Cliopatria is new_name in Polity. Args: displayed_year (str): The year to display the polities for. "all" will return all polities. Any given year will return polities that were active in that year. @@ -3887,12 +3887,12 @@ def get_polity_shape_content(displayed_year="all", seshat_id="all", tick_number= raise ValueError("Only one of displayed_year or seshat_id should be set not both.") if displayed_year != "all": - rows = VideoShapefile.objects.filter(polity_start_year__lte=displayed_year, polity_end_year__gte=displayed_year) + rows = Cliopatria.objects.filter(polity_start_year__lte=displayed_year, polity_end_year__gte=displayed_year) elif seshat_id != "all": # Note: this query assumes that some polities have multiple seshat_ids separated by a semicolon, but none are included inside a different longer seshat_id - rows = VideoShapefile.objects.filter(seshat_id__contains=seshat_id) + rows = Cliopatria.objects.filter(seshat_id__contains=seshat_id) else: - rows = VideoShapefile.objects.all() + rows = Cliopatria.objects.all() # Convert 'geom' to GeoJSON in the database query rows = rows.annotate(geom_json=AsGeoJSON('geom')) @@ -3909,7 +3909,7 @@ def get_polity_shape_content(displayed_year="all", seshat_id="all", tick_number= seshat_id_page_id = {new_name: {'id': id, 'long_name': long_name or ""} for new_name, id, long_name in polity_info} if 'migrate' not in sys.argv: - result = VideoShapefile.objects.aggregate( + result = Cliopatria.objects.aggregate( min_year=Min('polity_start_year'), max_year=Max('polity_end_year') ) @@ -4316,12 +4316,12 @@ def random_polity_shape(from_selection=True): ] # Select a random polity from the list seshat_id = random.choice(selected_polities) - shape = VideoShapefile.objects.filter(seshat_id=seshat_id).first() + shape = Cliopatria.objects.filter(seshat_id=seshat_id).first() else: - max_id = VideoShapefile.objects.filter(seshat_id__isnull=False).aggregate(max_id=Max("id"))['max_id'] + max_id = Cliopatria.objects.filter(seshat_id__isnull=False).aggregate(max_id=Max("id"))['max_id'] while True: pk = random.randint(1, max_id) - shape = VideoShapefile.objects.filter(seshat_id__isnull=False, id=pk).first() + shape = Cliopatria.objects.filter(seshat_id__isnull=False, id=pk).first() if shape: if shape.seshat_id and shape.area > 600000: # Big empires only break diff --git a/seshat/apps/seshat_api/filters/core.py b/seshat/apps/seshat_api/filters/core.py index a0487813e..c68e9fd9e 100644 --- a/seshat/apps/seshat_api/filters/core.py +++ b/seshat/apps/seshat_api/filters/core.py @@ -17,7 +17,7 @@ SeshatCommentPart, ScpThroughCtn, Religion, - VideoShapefile, + Cliopatria, GADMShapefile, GADMCountries, GADMProvinces, @@ -284,9 +284,9 @@ class Meta: } -class VideoShapefileFilter(django_filters.FilterSet): +class CliopatriaFilter(django_filters.FilterSet): class Meta: - model = VideoShapefile + model = Cliopatria fields = { "name": ["icontains", "exact"], "wikipedia_name": ["icontains", "exact"], diff --git a/seshat/apps/seshat_api/models.py b/seshat/apps/seshat_api/models.py index 42bf15b9e..13302fbcb 100644 --- a/seshat/apps/seshat_api/models.py +++ b/seshat/apps/seshat_api/models.py @@ -17,7 +17,7 @@ SeshatCommentPart, ScpThroughCtn, Religion, - VideoShapefile, + Cliopatria, GADMShapefile, GADMCountries, GADMProvinces, @@ -254,7 +254,7 @@ "SeshatCommentPart", "ScpThroughCtn", "Religion", - "VideoShapefile", + "Cliopatria", "GADMShapefile", "GADMCountries", "GADMProvinces", diff --git a/seshat/apps/seshat_api/urls.py b/seshat/apps/seshat_api/urls.py index c76ac207a..f11a84e2d 100644 --- a/seshat/apps/seshat_api/urls.py +++ b/seshat/apps/seshat_api/urls.py @@ -45,7 +45,7 @@ SeshatCommentPartViewSet, ScpThroughCtnViewSet, ReligionViewSet, - VideoShapefileViewSet, + CliopatriaViewSet, GADMShapefileViewSet, GADMCountriesViewSet, GADMProvincesViewSet, @@ -96,7 +96,7 @@ router.register(r"core/religions", ReligionViewSet, basename="religion") router.register( r"core/video-shapefiles", - VideoShapefileViewSet, + CliopatriaViewSet, basename="video-shapefile", ) router.register( diff --git a/seshat/apps/seshat_api/views/core.py b/seshat/apps/seshat_api/views/core.py index 658f564ef..d56471ab9 100644 --- a/seshat/apps/seshat_api/views/core.py +++ b/seshat/apps/seshat_api/views/core.py @@ -28,7 +28,7 @@ SeshatCommentPartFilter, ScpThroughCtnFilter, ReligionFilter, - VideoShapefileFilter, + CliopatriaFilter, GADMShapefileFilter, GADMCountriesFilter, GADMProvincesFilter, @@ -53,7 +53,7 @@ SeshatCommentPart, ScpThroughCtn, Religion, - VideoShapefile, + Cliopatria, GADMShapefile, GADMCountries, GADMProvinces, @@ -337,7 +337,7 @@ class ReligionViewSet( filterset_class = ReligionFilter -class VideoShapefileViewSet( +class CliopatriaViewSet( FilterBackends, MixinSeshatAPISerializer, MixinSeshatAPIAuth, @@ -347,9 +347,9 @@ class VideoShapefileViewSet( A viewset for viewing and editing Video Shapefiles. """ - model = VideoShapefile + model = Cliopatria pagination_class = SeshatAPIRestrictedPagination - filterset_class = VideoShapefileFilter + filterset_class = CliopatriaFilter class GADMShapefileViewSet( From f86660bfed26e236ac57ddf8f595e54ffacb07bb Mon Sep 17 00:00:00 2001 From: Ed Chalstrey Date: Fri, 6 Sep 2024 10:51:47 +0100 Subject: [PATCH 5/5] add shape info to polity map tooltip --- .../apps/core/templates/core/polity_map.html | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/seshat/apps/core/templates/core/polity_map.html b/seshat/apps/core/templates/core/polity_map.html index 1dd8b4c05..4068516ba 100644 --- a/seshat/apps/core/templates/core/polity_map.html +++ b/seshat/apps/core/templates/core/polity_map.html @@ -314,6 +314,18 @@

Background map

displayend_year = shape.polity_end_year + ' CE'; } + if (parseInt(shape.start_year) < 0) { + shapestart_year = Math.abs(parseInt(shape.start_year)) + ' BCE'; + } else { + shapestart_year = shape.start_year + ' CE'; + } + + if (parseInt(shape.end_year) < 0) { + shapeend_year = Math.abs(parseInt(shape.end_year)) + ' BCE'; + } else { + shapeend_year = shape.end_year + ' CE'; + } + let wiki_page = 'https://en.wikipedia.org/wiki/' + shape.wikipedia_name.replace(/ /g, '_'); var popupContent = ` @@ -333,6 +345,14 @@

Background map

+ + + + + + + +
Area (est.) ${formattedArea} Km2
Shapefile ID${parseInt(shape.id).toLocaleString()}
Shapefile years${shapestart_year} to ${shapeend_year}
`;