Skip to content

Commit

Permalink
Support #351
Browse files Browse the repository at this point in the history
  • Loading branch information
nutjob4life committed Apr 1, 2024
1 parent add9110 commit 1874870
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 15 deletions.
6 changes: 5 additions & 1 deletion src/eke.biomarkers/src/eke/biomarkers/biomarkerindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,10 @@ class BiomarkerIndex(KnowledgeFolder):
page_description = 'Container for biomarkers'

def get_vocabulary(self, name) -> list:
'''Get a "vocabulary" of known values for the field ``name`` for our contained subpage.'''
'''Get a "vocabulary" of known values for the field ``name`` for our contained subpage.
This function is not used.
'''
if name == 'organ':
return BiomarkerBodySystem.objects.values_list('title', flat=True).distinct().order_by(Lower('title'))
elif name == 'phase':
Expand All @@ -231,6 +234,7 @@ def get_contents(self, request: HttpRequest) -> object:
return matches

def faceted_markup(self, request):
'''Since we moved to DataTables, this function is no longer used.'''
pages, rows = self.get_contents(request), []
for page in pages:
rows.append(render_to_string('eke.biomarkers/biomarker-row.html', {'biomarker': page.specific}))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 4.2.10 on 2024-03-27 19:50

from django.db import migrations, models
import django.db.models.deletion
import modelcluster.fields


class Migration(migrations.Migration):
dependencies = [
("ekeknowledge", "0018_protocol_outcome_protocol_secure_outcome"),
]

operations = [
migrations.RemoveField(
model_name="protocol",
name="fieldOfResearch",
),
migrations.CreateModel(
name="ProtocolFieldOfResearch",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"sort_order",
models.IntegerField(blank=True, editable=False, null=True),
),
(
"value",
models.CharField(
default="Field of research",
help_text="Field of research",
max_length=25,
),
),
(
"page",
modelcluster.fields.ParentalKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="fields_of_research",
to="ekeknowledge.protocol",
),
),
],
options={
"ordering": ["sort_order"],
"abstract": False,
},
),
]
49 changes: 39 additions & 10 deletions src/eke.knowledge/src/eke/knowledge/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
from django.db.models import Q
from django.db.models.fields import Field
from django.db.models.functions import Lower
from django.http import HttpRequest
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.text import slugify
from django_plotly_dash import DjangoDash
from modelcluster.fields import ParentalManyToManyField
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from urllib.parse import urlparse
from wagtail.admin.panels import FieldPanel
from wagtail.admin.panels import FieldPanel, InlinePanel
from wagtail.models import Orderable
from wagtail.search import index
import dash_core_components as dcc
import dash_html_components as html
Expand Down Expand Up @@ -103,7 +104,6 @@ class Protocol(KnowledgeObject):
abbreviation = models.CharField(
max_length=120, null=False, blank=True, help_text='Short and more convenient name for the protocol'
)
fieldOfResearch = models.CharField(max_length=25, null=False, blank=True, help_text='Field this protocol studies')
phasedStatus = models.PositiveIntegerField(blank=True, null=True, help_text='Not sure what this is')
aims = models.TextField(null=False, blank=True, help_text='The long term goals of this protocol')
analyticMethod = models.TextField(null=False, blank=True, help_text='How things in this protocol are analyzed')
Expand All @@ -117,14 +117,14 @@ class Protocol(KnowledgeObject):
outcome = models.TextField(null=False, blank=True, help_text="What this protocol's net result was")
secure_outcome = models.TextField(null=False, blank=True, help_text="What this protocol's secret net result was")
content_panels = KnowledgeObject.content_panels + [
InlinePanel('fields_of_research', label='Fields of Research'), # 351
FieldPanel('coordinatingInvestigatorSite'),
FieldPanel('leadInvestigatorSite'),
FieldPanel('involvedInvestigatorSites'),
FieldPanel('cancer_types'),
FieldPanel('isProject'),
FieldPanel('protocolID'),
FieldPanel('abbreviation'),
FieldPanel('fieldOfResearch'),
FieldPanel('phasedStatus'),
FieldPanel('aims'),
FieldPanel('analyticMethod'),
Expand All @@ -141,7 +141,6 @@ class Protocol(KnowledgeObject):
search_fields = KnowledgeObject.search_fields + [
index.SearchField('abbreviation'),
index.SearchField('protocolID'),
index.FilterField('fieldOfResearch'),
index.FilterField('piName'),
index.FilterField('collaborativeGroup'),
index.FilterField('cancer_types'),
Expand All @@ -158,7 +157,7 @@ class RDFMeta:
esu('cancerType'): RelativeRDFAttribute('cancer_types', scalar=False),
esu('projectFlag'): _ProjectFlagRDFAttribute('isProject', scalar=True),
esu('abbreviatedName'): RDFAttribute('abbreviation', scalar=True),
esu('fieldOfResearch'): RDFAttribute('fieldOfResearch', scalar=True),
esu('fieldOfResearch'): RDFAttribute('fields_of_research', scalar=False), # #351
esu('collaborativeGroupText'): _CollaborativeGroupRDFAttribute('collaborativeGroup', scalar=True),
esu('phasedStatus'): RDFAttribute('phasedStatus', scalar=True),
esu('aims'): RDFAttribute('aims', scalar=True),
Expand Down Expand Up @@ -213,6 +212,9 @@ def get_context(self, request: HttpRequest, *args, **kwargs) -> dict:
# that we don't show the secure outcome
context['show_secure_outcome'] = False

# Fields of research ("f_o_rs") is multi-valued now #351
context['f_o_rs'] = [i for i in self.fields_of_research.all().order_by('value')]

return context

def data_table(self) -> dict:
Expand All @@ -232,17 +234,33 @@ def data_table(self) -> dict:
if cg == 'Breast': cg = 'Breast/Gyn'
cgs.append(cg)

# #351 — f_o_rs = "fields of research", which I guess technically should be "fs_o_r" 😅
f_o_rs = ', '.join([i for i in self.fields_of_research.all().values_list('value', flat=True).order_by('value')])

return {
'pi_name': pi_name,
'pi_url': pi_url,
'field': self.fieldOfResearch,
'f_o_rs': f_o_rs,
# Turned off for #190
# 'diseases': ', '.join([str(i) for i in self.cancer_types.values_list('title', flat=True).order_by('title')]),
'cg': ', '.join(cgs),
**super().data_table()
}


class ProtocolFieldOfResearch(Orderable):
'''Multi-valued support for RDF "fieldOfResearch" field.
Supports #351.
'''
value = models.CharField(
max_length=25, blank=False, null=False, default='Field of research', help_text='Field of research'
)
page = ParentalKey(Protocol, on_delete=models.CASCADE, related_name='fields_of_research')
panels = [FieldPanel('value')]
def __str__(self): return self.value # noqa: E704


class Ingestor(BaseIngestor):
def _dmcc_code(self, uri: rdflib.URIRef) -> str:
'''For the given subject URI return what would be the DMCC protocol ID.'''
Expand Down Expand Up @@ -324,7 +342,7 @@ def get_contents(self, request: HttpRequest) -> object:
pi, fields, cg = request.GET.get('piName'), request.GET.getlist('fieldOfResearch'), request.GET.get('collab_group')
filter = {}
if pi: filter['piName__exact'] = pi
if fields: filter['fieldOfResearch__in'] = fields
if fields: filter['fields_of_research__value__in'] = fields
if cg: filter['collaborativeGroup'] = cg # cannot use __contains or __icontains because ``search`` below balks
q = Q(**filter)
# According to https://docs.wagtail.org/en/stable/topics/search/indexing.html:
Expand Down Expand Up @@ -387,7 +405,7 @@ def get_context(self, request: HttpRequest, *args, **kwargs) -> dict:
# diseases_frame = pandas.DataFrame(diseases_facets.items(), columns=('Disease', 'Count'))
# except AttributeError:

c = collections.Counter(matches.values_list('fieldOfResearch', flat=True))
c = collections.Counter(matches.values_list('fields_of_research__value', flat=True))
fields, amounts = [i[0] for i in c.items()], [i[1] for i in c.items()]
fields_frame = pandas.DataFrame({'Field': fields, 'Count': amounts})
fields_legend = ghetto_plotly_legend([i[0] for i in c.most_common()], palette)
Expand Down Expand Up @@ -450,6 +468,17 @@ def get_context(self, request: HttpRequest, *args, **kwargs) -> dict:
])
return context

def serve(self, request: HttpRequest) -> HttpResponse:
'''Overridden service.
We override serve in order to handle the ``ajax=fields-of-research`` request. Supports #351.
'''
if request.GET.get('ajax') == 'fields-of-research':
f_o_rs = ProtocolFieldOfResearch.objects.distinct().values_list('value', flat=True).order_by('value')
return JsonResponse({'data': [i for i in f_o_rs]})
else:
return super().serve(request)

class Meta:
pass
class RDFMeta:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
else
return '<a href="' + row['pi_url'] + '">' + data + '</a>';
}},
{data: 'field'},
{data: 'f_o_rs'}, // #351
{# {data: 'diseases'}, Turned off for #190 #}
{data: 'cg'}
],
Expand All @@ -93,6 +93,7 @@
dom: "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>B",
initComplete: function() {
// Set up the collaborative group selector
var cg_col = this.api().column(4);
var select = $('<select><option value="">— Collab Group —</option></select>')
.appendTo($(cg_col.header()).empty())
Expand All @@ -105,7 +106,10 @@
select.append('<option value="Lung">Lung</option>');
select.append('<option value="Prostate">Prostate</option>');
select.append('<option value="UNKNOWN">UNKNOWN</option>');
this.api().columns([2, 3]).every(function() {

// Col 2 = PI; we used to do this on col 3 as well but now that it has multiple
// values per protocol we need to handle it specially
this.api().columns([2]).every(function() {
var column = this;
var label = this.footer().innerHTML;
var select = $('<select><option value="">— ' + label + ' —</option></select>')
Expand All @@ -118,6 +122,8 @@
select.append('<option value="' + d + '">' + d + '</option>');
});
});

// Col 0 = protocol title, col 1 = abstract
this.api().columns([0, 1]).every(function() {
var that = this;
$('input', this.header()).on('keyup change clear', function() {
Expand All @@ -126,6 +132,27 @@
}
});
});

// col 3 = field of research; requires special handling due to multiple values
// per protocol; #351
var f_o_r_column = this.api().column(3);
var f_o_r_select = $('<select><option value="">— Field —</option></select>')
.appendTo($(f_o_r_column.header()).empty())
.on('change', function() {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
f_o_r_column.search(val? val : '', true, false).draw();
});
var f_o_r_retriever = new XMLHttpRequest();
f_o_r_retriever.open('GET', '{% pageurl page %}?ajax=fields-of-research', true);
f_o_r_retriever.onreadystatechange = function() {
if (f_o_r_retriever.readyState === 4 && f_o_r_retriever.status === 200) {
var f_o_rs = JSON.parse(f_o_r_retriever.responseText)['data'];
f_o_rs.forEach(f_o_r => {
f_o_r_select.append('<option value="' + f_o_r + '">' + f_o_r + '</option>');
})
}
}
f_o_r_retriever.send();
}
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,19 @@ <h5><span class='badge bg-secondary'><i class='bi-asterisk'></i>  Non-EDRN Prot
<dt>Protocol Type</dt>
<dd>{{page.kind}}</dd>
{% endif %}
<dt>Field of Research</dt>
<dd>{{page.fieldOfResearch}}</dd>

{% if f_o_rs %}
{# #351 #}
<dt>Fields of Research</dt>
<dd>
<ul class='list-unstyled'>
{% for f_o_r in f_o_rs %}
<li>{{f_o_r}}</li>
{% endfor %}
</ul>
</dd>
{% endif %}

<dt>Collaborative Group</dt>
<dd>
{% if page.collaborativeGroup %}
Expand Down

0 comments on commit 1874870

Please sign in to comment.