Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create API endpoint for proximity analysis #53

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions backend/app/analysis/proximity.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def run_analysis(corpus_id, word_window):
genders,
word_window
)
breakpoint()

return results

Expand All @@ -55,12 +54,12 @@ def generate_gender_token_counters(pos_tags, genders, word_window):
results = {}

for gender in genders:
results[gender] = dict()
results[str(gender)] = dict()

for PRONOUN_TYPE in PronounSeries.PRONOUN_TYPES:
pronoun_set = gender.pronoun_series.values_list(PRONOUN_TYPE, flat=True)
doc_result = generate_token_counter(pos_tags, pronoun_set, word_window)
results[gender][PRONOUN_TYPE] = doc_result
results[str(gender)][PRONOUN_TYPE] = doc_result

return results

Expand Down
18 changes: 18 additions & 0 deletions backend/app/analysis/proximity_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from ..models import Document, Corpus
from rest_framework.test import APIRequestFactory
from app.views import add_proximity_analysis


def proximity_view_test(text):
"""A function for testing the proximity analysis posting,
check api/all_proximity to see the updates list
"""
c1 = Corpus(title="Corpus Test", description="This is the testing corpus")
c1.save()
Document.objects.create_document(title='document_1', year=2021, text=text)
d1 = Document.objects.get(title='document_1')
c1.documents.add(d1)
factory = APIRequestFactory()
request = factory.post('api/all_proximity', {'word_window': '2', 'corpus_id': c1.id})
add_proximity_analysis(request)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this test used simply to manually ensure that the full ProximityAnalysis creation occurred as expected? Would it be possible to add something to our larger test suite so we can check that the model instance is saved as expected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, this was just a manual test. I will try and add a more comprehensive test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just added a test to the tests.py file that makes sure the post request is successful

47 changes: 42 additions & 5 deletions backend/app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,24 @@
'component_name': 'ExampleId'
}
"""
import json

from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.shortcuts import render
from .models import (
Document,
Gender,
Corpus
Corpus,
ProximityAnalysis
)
from .serializers import (
DocumentSerializer,
SimpleDocumentSerializer,
GenderSerializer,
CorpusSerializer
CorpusSerializer,
ProximityAnalysisSerializer,
)

from .analysis.proximity import run_analysis

@api_view(['GET'])
def get_example(request, example_id):
Expand Down Expand Up @@ -243,6 +244,43 @@ def get_corpus(request, corpus_id):
return Response(serializer.data)


@api_view(['GET'])
def all_proximity(request):
prox_objs = ProximityAnalysis.objects.all()
serializer = ProximityAnalysisSerializer(prox_objs, many=True)
return Response(serializer.data)


@api_view(['POST'])
def add_proximity_analysis(request):
"""
API endpoint for posting the proximity analysis
"""
attributes = request.data
corpus_id = int(attributes['corpus_id'])
word_window = int(attributes['word_window'])

proximity_query = ProximityAnalysis.objects.filter(corpus__id=corpus_id, word_window=word_window)

if proximity_query.exists():
proximity_obj = proximity_query.get()

else:
results = run_analysis(corpus_id, word_window)
fields = {
'corpus': Corpus.objects.get(pk=corpus_id),
'word_window': word_window,
'results': results,
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultimately, we may want to change this up so that you call a ProximityAnalysisManager or similar (like we do with the DocumentManager) when we create this new ProximityAnalysis, and have the ProximityAnalysisManager call the run_analysis function. That is: since a ProximityAnalysis necessarily relies on the run_analysis function, we could use the ProximityAnalysis itself (through a Manager) to ensure that run_analysis is run when a new instance is created. That would more tightly couple associated functionality. That said, since this is working and is well tested, we can leave it be for now and come back to it later.

proximity_obj = ProximityAnalysis.objects.create(**fields)
gender_ids = list(Gender.objects.values_list('pk', flat=True))
proximity_obj.genders.add(*gender_ids)

serializer = ProximityAnalysisSerializer(proximity_obj)
return Response(serializer.data)


def corpora(request):
"""
Corpora page
Expand Down Expand Up @@ -274,4 +312,3 @@ def corpus(request, corpus_id):
}

return render(request, 'index.html', context)

2 changes: 2 additions & 0 deletions backend/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
path('api/update_corpus_docs', views.update_corpus_docs),
path('api/delete_corpus', views.delete_corpus),
path('api/corpus/<int:corpus_id>', views.get_corpus),
path('api/proximity', views.add_proximity_analysis),
path('api/all_proximity', views.all_proximity),

# View paths
path('', views.index, name='index'),
Expand Down