Skip to content

Commit

Permalink
Merge pull request #87 from Seshat-Global-History-Databank/cliopatria…
Browse files Browse the repository at this point in the history
…-table

Rename cliopatria table & add shape ID
  • Loading branch information
edwardchalstrey1 authored Sep 6, 2024
2 parents 53afb27 + f86660b commit e52ad07
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 43 deletions.
4 changes: 2 additions & 2 deletions docs/source/admin/setup/spatialdb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions seshat/apps/core/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',

Expand All @@ -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)'}),

}
Expand All @@ -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',
Expand All @@ -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)'}),

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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'],
Expand All @@ -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'))
Expand Down
Original file line number Diff line number Diff line change
@@ -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',
),
]
2 changes: 1 addition & 1 deletion seshat/apps/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1129,7 +1129,7 @@ def __str__(self) -> str:

# Shapefile models

class VideoShapefile(models.Model):
class Cliopatria(models.Model):
"""
Model representing Cliopatria polity borders dataset.
"""
Expand Down
20 changes: 20 additions & 0 deletions seshat/apps/core/templates/core/polity_map.html
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,18 @@ <h2 class="text-teal federicka-medium">Background map</h2>
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 = `
<table>
Expand All @@ -333,6 +345,14 @@ <h2 class="text-teal federicka-medium">Background map</h2>
<td>Area (est.)</td>
<td>${formattedArea} Km<sup>2</sup></td>
</tr>
<tr>
<td>Shapefile ID</td>
<td>${parseInt(shape.id).toLocaleString()}</td>
</tr>
<tr>
<td>Shapefile years</td>
<td>${shapestart_year} to ${shapeend_year}</td>
</tr>
</table>
`;

Expand Down
10 changes: 5 additions & 5 deletions seshat/apps/core/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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):
Expand Down
18 changes: 9 additions & 9 deletions seshat/apps/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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'))
Expand All @@ -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')
)
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions seshat/apps/seshat_api/filters/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
SeshatCommentPart,
ScpThroughCtn,
Religion,
VideoShapefile,
Cliopatria,
GADMShapefile,
GADMCountries,
GADMProvinces,
Expand Down Expand Up @@ -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"],
Expand Down
4 changes: 2 additions & 2 deletions seshat/apps/seshat_api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
SeshatCommentPart,
ScpThroughCtn,
Religion,
VideoShapefile,
Cliopatria,
GADMShapefile,
GADMCountries,
GADMProvinces,
Expand Down Expand Up @@ -254,7 +254,7 @@
"SeshatCommentPart",
"ScpThroughCtn",
"Religion",
"VideoShapefile",
"Cliopatria",
"GADMShapefile",
"GADMCountries",
"GADMProvinces",
Expand Down
4 changes: 2 additions & 2 deletions seshat/apps/seshat_api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
SeshatCommentPartViewSet,
ScpThroughCtnViewSet,
ReligionViewSet,
VideoShapefileViewSet,
CliopatriaViewSet,
GADMShapefileViewSet,
GADMCountriesViewSet,
GADMProvincesViewSet,
Expand Down Expand Up @@ -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(
Expand Down
10 changes: 5 additions & 5 deletions seshat/apps/seshat_api/views/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
SeshatCommentPartFilter,
ScpThroughCtnFilter,
ReligionFilter,
VideoShapefileFilter,
CliopatriaFilter,
GADMShapefileFilter,
GADMCountriesFilter,
GADMProvincesFilter,
Expand All @@ -53,7 +53,7 @@
SeshatCommentPart,
ScpThroughCtn,
Religion,
VideoShapefile,
Cliopatria,
GADMShapefile,
GADMCountries,
GADMProvinces,
Expand Down Expand Up @@ -337,7 +337,7 @@ class ReligionViewSet(
filterset_class = ReligionFilter


class VideoShapefileViewSet(
class CliopatriaViewSet(
FilterBackends,
MixinSeshatAPISerializer,
MixinSeshatAPIAuth,
Expand All @@ -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(
Expand Down

0 comments on commit e52ad07

Please sign in to comment.