-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathassertion.html
308 lines (301 loc) · 16.4 KB
/
assertion.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>{{ title }}</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
<style>
li::marker {
content: "";
}
</style>
</head>
<body>
<main role="main" class="container-fluid">
<h4 class="text-center">
Assertion:
<span class="badge bg-primary">
{% if assertion.subject_uniprot %}
{{ assertion.subject_uniprot.uniprot }}
{% else %}
{{ assertion.subject_curie }}
{% endif %}
</span>
{% for predicate in assertion.get_predicates() %}
<span class="badge bg-secondary">{{ predicate.replace('biolink:', '') }}</span>
{% endfor %}
<span class="badge bg-info">
{% if assertion.object_uniprot %}
{{ assertion.object_uniprot.uniprot }}
{% else %}
{{ assertion.object_curie }}
{% endif %}
</span>
</h4>
<div class="accordion" id="evidenceAccordion">
{% for ev in assertion.get_current_evidences()[:500] %}
{% if ev.get_top_predicate() != 'false' %}
<div class="accordion-item">
<h2 class="accordion-header" id="header_{{ ev.evidence_id }}">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
data-bs-target="#collapse_{{ ev.evidence_id }}" aria-expanded="false" aria-controls="collapse_{{ ev.evidence_id }}">
<span id="{{ ev.evidence_id }}_2" class="evidence_sentence"
data-subject-span="{{ ev.subject_entity.span }}"
data-subject-text="{{ ev.subject_entity.covered_text }}"
data-subject-curie="{% if ev.assertion.subject_uniprot %} {{ ev.assertion.subject_uniprot.uniprot }} {% else %} {{ ev.assertion.subject_curie }} {% endif %}"
data-object-span="{{ ev.object_entity.span }}"
data-object-text="{{ ev.object_entity.covered_text }}"
data-object-curie="{% if ev.assertion.object_uniprot %} {{ ev.assertion.object_uniprot.uniprot }} {% else %} {{ ev.assertion.object_curie }} {% endif %}">
{{ ev.sentence }}
</span>
</button>
</h2>
<div id="collapse_{{ ev.evidence_id }}" class="accordion-collapse collapse" aria-labelledby="header_{{ ev.evidence_id }}" data-bs-parent="evidenceAccordion">
<dl class="row">
<dt class="col-sm-2">Publication:</dt> <dd class="col-sm-10"><a target="_blank" href="https://pubmed.ncbi.nlm.nih.gov/{{ ev.document_id.replace('PMID:', '') }}">{{ ev.document_id }}<small><i class="bi bi-box-arrow-up-right"></i></small></a></dd>
<dt class="col-sm-2">Publication Year:</dt> <dd class="col-sm-10">{{ ev.actual_year.year }}</dd>
<dt class="col-sm-2">Document Zone:</dt> <dd class="col-sm-10">{{ ev.document_zone }}</dd>
<dt class="col-sm-2">Predicate:</dt> <dd class="col-sm-10">{{ ev.get_top_predicate() }}</dd>
<dt class="col-sm-2">Confidence:</dt> <dd class="col-sm-10">{{ ev.get_score() }}</dd>
</dl>
<button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#feedbackModal"
id="feedbackBtn_{{ ev.evidence_id }}"
data-evidence-id="{{ ev.evidence_id }}"
data-sentence-id="{{ ev.evidence_id }}_2"
data-subject-curie="{% if ev.assertion.subject_uniprot %} {{ ev.assertion.subject_uniprot.uniprot }} {% else %} {{ ev.assertion.subject_curie }} {% endif %}"
data-subject-text="{{ ev.subject_entity.covered_text }}"
data-object-text="{{ ev.object_entity.covered_text }}"
data-object-curie="{% if ev.assertion.object_uniprot %} {{ ev.assertion.object_uniprot.uniprot }} {% else %} {{ ev.assertion.object_curie }} {% endif %}"
data-predicate="{{ ev.get_top_predicate() }}">
Send feedback
</button>
</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="modal" id="feedbackModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Feedback</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Sentence:
<p id="feedbackSentence" data-evidence-id></p>
Assertion:
<p>
<span id="feedbackSubject" class="badge bg-primary"></span>
<span id="feedbackPredicate" class="badge bg-secondary"></span>
<span id="feedbackObject" class="badge bg-info"></span>
</p>
<div class="p-2">
<h5>Correct</h5>
<div class="form-check">
<input class="form-check-input feedback" type="checkbox" value="Assertion Correct" id="overallCheck">
<label class="form-check-label" for="overallCheck" data-bs-toggle="tooltip" title="Use this option to indicate that the text-mined assertion accurately represents the relationship asserted by the sentence between the subject and object entity.">
The text supports this assertion
</label>
</div>
</div>
<div class="p-2">
<h5>Incorrect</h5>
<div class="form-check">
<input class="form-check-input feedback" type="checkbox" value="Assertion Incorrect" id="noAssertion">
<label class="form-check-label" for="noAssertion" data-bs-toggle="tooltip" title="Use this option to indicate that the text does not support the asserted relation between the subject and object entity. Select sub-options as appropriate.">
The text does not support this assertion
</label>
</div>
<ul><li class="unbulleted">
<div class="form-check">
<input class="form-check-input feedback incorrect" type="checkbox" value="Predicate Incorrect" id="badPredicate">
<label class="form-check-label" for="badPredicate" data-bs-toggle="tooltip" title="Use this option to indicate that the text does not support the predicate used in the assertion, e.g., if the assertion uses biolink:treats when the sentence instead asserts a biolink:causes relationship.">
The text does not support the predicate of the assertion (<span class="badge bg-secondary predicate-curie"></span>)
</label>
</div>
<ul><li class="unbulleted">
<div class="form-check">
<input class="form-check-input feedback incorrect" type="checkbox" value="Predicate Too Specific" id="tooSpecific">
<label class="form-check-label" for="tooSpecific" data-bs-toggle="tooltip" title="Use this option to indicate that the text does not support the predicate used in the assertion because the predicate is too specific, e.g., the assertion uses biolink:causes when it should instead use biolink:contributes_to.">
The predicate of the assertion (<span class="badge bg-secondary predicate-curie"></span>) is too specific
</label>
</div>
</li></ul>
<div class="form-check">
<input class="form-check-input feedback incorrect" type="checkbox" value="Incorrect Subject" id="badSubject">
<label class="form-check-label" for="badSubject" data-bs-toggle="tooltip" title="Use this option to indicate that a concept recognition error has occurred for the subject entity.">
The annotated subject text does not refer to the subject class (<span class="badge bg-primary subject-curie"></span>) of the assertion
</label>
</div>
<div class="form-check">
<input class="form-check-input feedback incorrect" type="checkbox" value="Incorrect Object" id="badObject">
<label class="form-check-label" for="badObject" data-bs-toggle="tooltip" title="Use this option to indicate that a concept recognition error has occurred for the object entity.">
The annotated object text does not refer to the object class (<span class="badge bg-info object-curie"></span>) of the assertion
</label>
</div>
</li></ul>
</div>
<div class="p-2">
<h5>This assertion could be improved</h5>
<div class="form-check">
<input class="form-check-input feedback" type="checkbox" value="Subject Too General" id="subjectGeneral">
<label class="form-check-label" for="subjectGeneral" data-bs-toggle="tooltip" title="Use this option to indicate that although the text supports the assertion, the assertion could be improved by using a more specific subject class and/or altering the highlighted span for the subject entity. If this is the case, please include an ontology identifier referencing a more appropriate class and include the text of any altered highlighted span.">
This assertion could be improved by using a more specific subject class/span (<span class="badge bg-primary subject-curie"></span>) (please suggest a more specific subject in the comment box below)
</label>
</div>
<div class="form-check">
<input class="form-check-input feedback" type="checkbox" value="Object Too General" id="objectGeneral">
<label class="form-check-label" for="objectGeneral" data-bs-toggle="tooltip" title="Use this option to indicate that although the text supports the assertion, the assertion could be improved by using a more specific object class and/or altering the highlighted span for the object entity. If this is the case, please include an ontology identifier referencing a more appropriate class and include the text of any altered highlighted span.">
This assertion could be improved by using a more specific object class/span (<span class="badge bg-info object-curie"></span>) (please suggest a more specific object in the comment box below)
</label>
</div>
<div class="form-check">
<input class="form-check-input feedback" type="checkbox" value="Predicate Too General" id="predicateGeneral">
<label class="form-check-label" for="predicateGeneral" data-bs-toggle="tooltip" title="Use this option to indicate that although the text supports the assertion, the predicate used is too general. If this is the case, please suggest an alternative predicate in the comment box.">
The text supports this assertion, but the predicate (<span class="badge bg-secondary predicate-curie"></span>) is too general (please suggest a more specific predicate in the comment box below)
</label>
</div>
</div>
<div class="mb-3">
<label for="comments" class="form-label">Additional Comments (optional):</label>
<input type="text" class="form-control" id="comments">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="submitButton">Send Feedback</button>
</div>
</div>
</div>
</div>
</main>
<script>
$(function() {
function insertStringAt(originalString, stringToAdd, index) {
return originalString.slice(0, index) + stringToAdd + originalString.slice(index);
}
function spliceStrings(originalString, spliceList) {
outputString = originalString;
spliceList.sort((a, b) => a[1] - b[1]);
var priorInsertLength = 0;
for(let i = 0; i < spliceList.length; i++) {
outputString = insertStringAt(outputString, spliceList[i][0], spliceList[i][1] + priorInsertLength);
priorInsertLength += spliceList[i][0].length;
}
return outputString;
}
function highlightText(id) {
sentenceElement = document.getElementById(id);
sentence = sentenceElement.innerText;
dataset = sentenceElement.dataset;
subject_start = parseInt(dataset.subjectSpan.split('|')[0], 10);
subject_end = parseInt(dataset.subjectSpan.split('|')[1], 10);
object_start = parseInt(dataset.objectSpan.split('|')[0], 10);
object_end = parseInt(dataset.objectSpan.split('|')[1], 10);
let spliceList = [
['<span class="badge bg-primary" data-bs-toggle="tooltip" title="' + dataset.subjectCurie + '">', subject_start],
['</span>', subject_end],
['<span class="badge bg-info" data-bs-toggle="tooltip" title="' + dataset.objectCurie + '">', object_start],
['</span>', object_end]
];
let sentenceHTML = spliceStrings(sentence, spliceList);
sentenceElement.innerHTML = sentenceHTML;
$('#' + id + '>span[data-bs-toggle="tooltip"]').tooltip();
}
function sendFeedback() {
if (!(document.getElementById('overallCheck').checked || document.getElementById('noAssertion').checked)) {
alert('Please indicate whether the assertion is correct or incorrect');
return;
}
feedbackObject = {
'evidence_id' : document.getElementById('feedbackSentence').dataset.evidenceId,
}
checks = document.getElementsByClassName('feedback');
for (const check of checks) {
feedbackObject[check.value] = check.checked;
}
commentText = document.getElementById('comments').value
if(commentText.length > 0) {
feedbackObject['comments'] = commentText;
}
$.ajax({
url : '/api/evidence/feedback',
type : 'POST',
dataType: 'json',
contentType: 'application/json;charset=utf-8',
data : JSON.stringify(feedbackObject),
success : function() {
feedbackBtn = $('#feedbackBtn_' + document.getElementById('feedbackSentence').dataset.evidenceId);
$('#feedbackModal').modal('hide');
feedbackBtn.prop('disabled', true);
feedbackBtn.html('Feedback sent')
},
error : function(request,error)
{
console.log("Request: " + JSON.stringify(request));
}
});
}
// Set up the modal to populate with the dataset of the button used to call it.
const feedbackModal = document.getElementById('feedbackModal');
feedbackModal.addEventListener('show.bs.modal', event => {
const button = event.relatedTarget;
document.getElementById('feedbackSentence').innerHTML = document.getElementById(button.dataset.sentenceId).innerHTML;
document.getElementById('feedbackSentence').dataset.evidenceId = button.dataset.evidenceId
document.getElementById('feedbackSubject').innerHTML = button.dataset.subjectText;
document.getElementById('feedbackObject').innerHTML = button.dataset.objectText;
document.getElementById('feedbackPredicate').innerHTML = button.dataset.predicate.replace('biolink:', '');
document.getElementById('comments').value = '';
$('.subject-curie').text(button.dataset.subjectCurie);
$('.object-curie').text(button.dataset.objectCurie);
$('.predicate-curie').text(button.dataset.predicate);
$('input[type=checkbox]').prop('checked', false);
$('#feedbackModal').find('[data-bs-toggle="tooltip"]').tooltip()
});
correctCheckbox = document.getElementById('overallCheck')
correctCheckbox.addEventListener('change', function() {
if (correctCheckbox.checked) {
$('#noAssertion').prop('checked', false);
$('.incorrect').prop('checked', false);
}
});
incorrectCheckbox = document.getElementById('noAssertion')
incorrectCheckbox.addEventListener('change', function() {
if (incorrectCheckbox.checked) {
$('#overallCheck').prop('checked', false);
} else {
$('.incorrect').prop('checked', false);
}
});
var checkboxes = document.querySelectorAll(".incorrect");
checkboxes.forEach(function(checkbox) {
checkbox.addEventListener('change', function() {
if (checkbox.checked) {
$('#noAssertion').prop('checked', true);
$('#overallCheck').prop('checked', false);
if (checkbox.id == 'tooSpecific') {
$('#badPredicate').prop('checked', true);
}
} else {
if (checkbox.id == 'badPredicate') {
$('#tooSpecific').prop('checked', false);
}
}
});
});
document.getElementById('submitButton').addEventListener('click', sendFeedback);
// Highlight the subject and object of every evidence sentence. This should be last to not block anything.
Array.prototype.forEach.call(document.getElementsByClassName('evidence_sentence'), function(element) {
highlightText(element.id);
});
});
</script>
</body>
</html>