Skip to content

Commit 142b60f

Browse files
crispzipsjdamerow
andauthored
Story/iexp 543 (#856)
* added theses by school over time data visualization dashboard * [IEXP-543] initial creation of genealogy playground data visualization tools * [story/IEXP-543] consolidated and modularized code, tidied, added domino chain reaction feature to genealogy visualizer, color coded advisors, add all nodes legend * [IEXP-543] some changes to theses by school code * [IEXP-553] moved some code away from views file * [IEXP-543] a little more cleanup * [IEXP-543] rename d3 source code and fix minor playground bug, some documentation for playground functions * [IEXP-543] a little bit of refactoring and moving things around * [IEXP-543] remove empty line --------- Co-authored-by: Julia Damerow <[email protected]>
1 parent d6157eb commit 142b60f

22 files changed

+1796
-147
lines changed

isiscb/isisdata/forms.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from haystack.forms import FacetedSearchForm
33
from django import forms
44
from django.db import models
5+
from django.db.models import Q, Count
56
from django.apps import apps
67
from django.utils.text import capfirst
78
#from django.utils.translation import ugettext_lazy as _
@@ -17,9 +18,11 @@
1718

1819
import time
1920
from isisdata import helper_methods
20-
from isisdata.models import Citation, Authority, Tenant
21+
from isisdata.models import Citation, Authority, Tenant, ACRelation
2122
from openurl.models import *
2223
from isisdata.utils import normalize
24+
import logging
25+
logger = logging.getLogger(__name__)
2326

2427
import re
2528

@@ -275,3 +278,47 @@ class UserProfileForm(forms.Form):
275278
bio = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}), required=False)
276279
share_email = forms.BooleanField(required=False)
277280
resolver_institution = forms.ModelChoiceField(queryset=Institution.objects.all(), widget=forms.Select(attrs={'class': 'form-control'}), required=False)
281+
282+
class ThesisMillForm(forms.Form):
283+
TOP5 = 5
284+
TOP10 = 10
285+
TOP25 = 25
286+
TOP50 = 50
287+
CUSTOM = "CU"
288+
TOP_CHOICES = [
289+
(TOP5, "Top 5 Schools"),
290+
(TOP10, "Top 10 Schools"),
291+
(TOP25, "Top 25 Schools"),
292+
(TOP50, "Top 50 Schools"),
293+
(CUSTOM, "Custom"),
294+
]
295+
296+
NORMALIZED_AREA = "NA"
297+
HEATGRID = "HG"
298+
AREA = "AR"
299+
STREAMGRAPH = "ST"
300+
CHART_CHOICES = [
301+
(NORMALIZED_AREA, "Normalized Area"),
302+
(HEATGRID, "Heatgrid"),
303+
(AREA, "Area"),
304+
(STREAMGRAPH, "Streamgraph"),
305+
]
306+
307+
chart_type = forms.ChoiceField(
308+
widget=forms.Select(attrs={'class':'form-control'}),
309+
choices=CHART_CHOICES,
310+
initial=STREAMGRAPH,
311+
label='Chart Type',
312+
)
313+
top = forms.ChoiceField(
314+
widget=forms.Select(attrs={'class':'form-control'}),
315+
choices=TOP_CHOICES,
316+
initial=TOP5,
317+
label='Schools',
318+
)
319+
select_schools = forms.ModelMultipleChoiceField(
320+
widget=forms.CheckboxSelectMultiple(),
321+
queryset=Authority.objects.filter(public=True, type_controlled=Authority.INSTITUTION, acrelation__type_controlled=ACRelation.SCHOOL).annotate(num_theses=Count('acrelation', filter=Q(acrelation__citation__type_controlled=Citation.THESIS))).filter(num_theses__gt=2).order_by('name'),
322+
required=False,
323+
label='Select Schools',
324+
)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
from django.views.decorators.csrf import ensure_csrf_cookie
2+
from django.shortcuts import render
3+
from django.http import JsonResponse
4+
from isisdata.models import Citation, Authority, ACRelation
5+
from isisdata.forms import ThesisMillForm
6+
7+
from isisdata.playground import *
8+
9+
import json
10+
11+
12+
@ensure_csrf_cookie
13+
def genealogy(request, tenant_id=None):
14+
context = {}
15+
16+
if request.method != 'POST':
17+
return render(request, 'isisdata/genealogy.html', context)
18+
19+
request = json.loads(request.body)
20+
subjects = request['subjects']
21+
domino_effect = request['domino']
22+
node_ids = set(subjects.copy())
23+
24+
subject_theses_ids = ACRelation.objects.filter(
25+
public=True,
26+
authority__public=True,
27+
citation__public=True,
28+
authority__id__in=subjects,
29+
citation__type_controlled=Citation.THESIS,
30+
type_controlled__in=[ACRelation.SCHOOL, ACRelation.AUTHOR, ACRelation.ADVISOR]
31+
)\
32+
.values_list("citation__id", flat=True).distinct("citation__id")
33+
34+
subject_theses = Citation.objects.filter(id__in=[subject_theses_ids])
35+
36+
nodes = []
37+
links = []
38+
39+
if subject_theses:
40+
for thesis in subject_theses:
41+
extrapolate_thesis(thesis, node_ids, links, domino_effect, subjects)
42+
43+
node_associations_min = 0
44+
node_associations_max = 0
45+
46+
if node_ids:
47+
node_authorities = Authority.objects.filter(pk__in=list(node_ids))
48+
for authority in node_authorities:
49+
node, node_association_count = generate_genealogy_node(authority, subjects)
50+
node_associations_min = node_association_count if node_association_count < node_associations_min else node_associations_min
51+
node_associations_max = node_association_count if node_association_count > node_associations_max else node_associations_max
52+
nodes.append(node)
53+
54+
node_associations_range = {
55+
'min': node_associations_min,
56+
'max': node_associations_max,
57+
}
58+
59+
context = {
60+
'nodes': json.dumps(nodes),
61+
'links': json.dumps(links),
62+
'subjects': subjects,
63+
'node_associations_range': node_associations_range,
64+
}
65+
66+
return JsonResponse(context)
67+
68+
@ensure_csrf_cookie
69+
def theses_by_school(request, tenant_id=None):
70+
form = ThesisMillForm()
71+
top = form.fields['top'].initial
72+
chart_type = form.fields['chart_type'].initial
73+
chart_type_urls = {
74+
"HG": "heatgrid",
75+
"NA": "normalized-area",
76+
"AR": "area",
77+
"ST": "streamgraph",
78+
}
79+
select_schools = []
80+
81+
if request.method == 'POST':
82+
form = ThesisMillForm(request.POST)
83+
if form.is_valid():
84+
chart_type = form.cleaned_data["chart_type"]
85+
top = form.cleaned_data["top"] if form.cleaned_data["top"] == "CU" else int(form.cleaned_data["top"])
86+
select_schools = form.cleaned_data["select_schools"]
87+
88+
context = generate_theses_by_school_context(top, chart_type, select_schools)
89+
90+
context["form"] = form
91+
context["top"] = top
92+
context["chart_url"] = chart_type_urls[chart_type]
93+
94+
return render(request, 'isisdata/theses_by_school.html', context)
95+

0 commit comments

Comments
 (0)