app/assets/javascripts/bp_annotatorplus.js
var
bp_last_params = null,
annotationsTable = null,
annotator_ontologies = null;
// Note: the configuration is in config/bioportal_config.rb.
var BP_CONFIG = jQuery(document).data().bp.config;
var BP_COLUMNS = {
classes: 0,
ontologies: 1,
types: 2,
sem_types: 3,
matched_classes: 5,
matched_ontologies: 6,
score: 7,
negation: 8,
experiencer: 9,
temporality: 10
};
var CONCEPT_MAP = {
"mapping": "mappedConcept",
"mgrep": "concept",
"closure": "concept"
};
function set_last_params(params) {
bp_last_params = params;
bp_last_params.apikey = BP_CONFIG.apikey; // TODO: get the user apikey?
//console.log(bp_last_params);
}
function insertSampleText(event) {
"use strict";
event.preventDefault();
var text = "The patient has no sign of melanoma but his father had skin cancer. The epithelial tissue cells show no abnormal activity.";
jQuery("#annotation_text").focus();
jQuery("#annotation_text").val(text);
}
function get_annotations() {
jQuery("#results_error").html("");
jQuery("#annotator_error").html("");
// Validation
if (!jQuery("#annotation_text").val()) {
jQuery("#annotator_error").html("Please enter text to annotate");
return;
}
// Really dumb, basic word counter.
if (jQuery("#annotation_text").val().split(' ').length > 500) {
jQuery("#annotator_error").html("Please use less than 500 words. If you need to annotate larger pieces of text you can use the <a href='http://www.bioontology.org/wiki/index.php/Annotator_User_Guide' target='_blank'>Annotator Web Service</a>");
return;
}
jQuery("#annotations_container").hide();
jQuery(".annotator_spinner").css('display', 'inline-block');
ajax_process_halt();
var params = {},
ont_select = jQuery("#ontology_ontologyId"),
mappings = [];
params.text = jQuery("#annotation_text").val();
params.ontologies = (ont_select.val() === null) ? [] : ont_select.val();
params.longest_only = jQuery("#longest_only").is(':checked');
params.exclude_numbers = jQuery("#exclude_numbers").is(':checked');
params.whole_word_only = jQuery("#whole_word_only").is(':checked');
params.exclude_synonyms = jQuery("#exclude_synonyms").is(':checked');
params.ncbo_slice = (("ncbo_slice" in BP_CONFIG) ? BP_CONFIG.ncbo_slice : '');
params.negation = jQuery("#negation").is(':checked');
params.experiencer = jQuery("#experiencer").is(':checked');
params.temporality = jQuery("#temporality").is(':checked');
params.score_threshold = jQuery("#score_threshold").val();
params.confidence_threshold = jQuery("#confidence_threshold").val();
params.score = jQuery("#score").val();
if (params.score) {
annotationsTable.fnSetColumnVis(BP_COLUMNS.score, true);
} else {
annotationsTable.fnSetColumnVis(BP_COLUMNS.score, false);
}
if (params.negation) {
annotationsTable.fnSetColumnVis(BP_COLUMNS.negation, true);
} else {
annotationsTable.fnSetColumnVis(BP_COLUMNS.negation, false);
}
if (params.experiencer) {
annotationsTable.fnSetColumnVis(BP_COLUMNS.experiencer, true);
} else {
annotationsTable.fnSetColumnVis(BP_COLUMNS.experiencer, false);
}
if (params.temporality) {
annotationsTable.fnSetColumnVis(BP_COLUMNS.temporality, true);
} else {
annotationsTable.fnSetColumnVis(BP_COLUMNS.temporality, false);
}
var maxLevel = parseInt(jQuery("#class_hierarchy_max_level").val());
if (maxLevel > 0) {
params.expand_class_hierarchy = "true";
params.class_hierarchy_max_level = maxLevel.toString();
}
// UI checkbox to control using the batch call in the controller.
params.raw = true; // do not use batch call to resolve class prefLabel and ontology names.
//if( jQuery("#use_ajax").length > 0 ) {
// params.raw = jQuery("#use_ajax").is(':checked');
//}
// Use the annotator default for wholeWordOnly = true.
//if (jQuery("#wholeWordOnly:checked").val() !== undefined) {
// params.wholeWordOnly = jQuery("#wholeWordOnly:checked").val();
//}
jQuery("[name='mappings']:checked").each(function() {
mappings.push(jQuery(this).val());
});
params.mappings = mappings;
if (jQuery("#semantic_types").val() !== null) {
params.semantic_types = jQuery("#semantic_types").val();
annotationsTable.fnSetColumnVis(BP_COLUMNS.sem_types, true);
jQuery("#results_error").html("Only results from ontologies with semantic types available are displayed.");
} else {
annotationsTable.fnSetColumnVis(BP_COLUMNS.sem_types, false);
}
if (jQuery("#semantic_groups").val() !== null) {
params.semantic_groups = jQuery("#semantic_groups").val();
annotationsTable.fnSetColumnVis(BP_COLUMNS.sem_types, true);
jQuery("#results_error").html("Only results from ontologies with semantic types available are displayed.");
} else {
annotationsTable.fnSetColumnVis(BP_COLUMNS.sem_types, false);
}
params["recognizer"] = jQuery("#recognizer").val();
jQuery.ajax({
type: "POST",
url: "/annotatorplus", // Call back to the UI annotation_controller::create method
data: params,
dataType: "json",
success: function(data) {
set_last_params(params);
display_annotations(data, bp_last_params);
jQuery(".annotator_spinner").hide();
jQuery("#annotations_container").show(300);
},
error: function(data) {
set_last_params(params);
jQuery(".annotator_spinner").hide();
jQuery("#annotations_container").hide();
jQuery("#annotator_error").html(" Problem getting annotations, please try again");
}
});
} // get_annotations
var displayFilteredColumnNames = function() {
"use strict";
var column_names = [];
var header_text;
jQuery(".bp_popup_list input:checked").closest("th").each(function() {
header_text = this.childNodes[0].textContent.trim();
column_names.push(header_text);
});
jQuery("#filter_names").html(column_names.join(", "));
if (column_names.length > 0) {
jQuery("#filter_list").show();
} else {
jQuery("#filter_list").hide();
}
};
function createFilterCheckboxes(filter_items, checkbox_class, checkbox_location) {
"use strict";
var for_sort = [],
sorted = [];
// Sort ontologies by number of results
jQuery.each(filter_items, function(k, v) {
for_sort.push({
label: k + " (" + v + ")",
count: v,
value: k,
value_encoded: encodeURIComponent(k)
});
});
for_sort.sort(function(a, b) {
return jQuery.trim(a.label) > jQuery.trim(b.label)
});
// Create checkboxes for ontology filter
jQuery.each(for_sort, function() {
var checkbox = jQuery("<input/>").attr("class", checkbox_class).attr("type", "checkbox").attr("value", this.value).attr("id", checkbox_class + this.value_encoded);
var label = jQuery("<label/>").attr("for", checkbox_class + this.value_encoded).html(" " + this.label);
sorted.push(jQuery("<span/>").append(checkbox).append(label).html());
});
jQuery("#" + checkbox_location).html(sorted.join("<br/>"));
}
var filter_ontologies = {
init: function() {
"use strict";
jQuery("#filter_ontologies").bind("click", function(e) {
bp_popup_init(e)
});
// Need to use bind to avoid "live" propogation issues
jQuery(".filter_ontology_checkboxes").bind("click", function(e) {
filter_ontologies.filterOntology(e)
});
jQuery("#ontology_filter_list").click(function(e) {
e.stopPropagation()
});
this.cleanup();
},
cleanup: function() {
"use strict";
jQuery("html").click(bp_popup_cleanup);
jQuery(document).keyup(function(e) {
if (e.keyCode == 27) {
bp_popup_cleanup();
} // esc
});
},
filterOntology: function(e) {
"use strict";
e.stopPropagation();
var search_regex = [];
jQuery(".filter_ontology_checkboxes:checked").each(function() {
search_regex.push(jQuery(this).val());
});
displayFilteredColumnNames();
if (search_regex.length === 0) {
annotationsTable.fnFilter("", BP_COLUMNS.ontologies);
} else {
annotationsTable.fnFilter(search_regex.join("|"), BP_COLUMNS.ontologies, true, false);
}
}
};
var filter_classes = {
init: function() {
"use strict";
jQuery("#filter_classes").bind("click", function(e) {
bp_popup_init(e)
});
// Need to use bind to avoid "live" propogation issues
jQuery(".filter_classes_checkboxes").bind("click", function(e) {
filter_classes.filterClasses(e)
});
jQuery("#classes_filter_list").click(function(e) {
e.stopPropagation()
});
this.cleanup();
},
cleanup: function() {
"use strict";
jQuery("html").click(bp_popup_cleanup);
jQuery(document).keyup(function(e) {
if (e.keyCode == 27) {
bp_popup_cleanup();
} // esc
});
},
filterClasses: function(e) {
"use strict";
e.stopPropagation();
var search_regex = [];
jQuery(".filter_classes_checkboxes:checked").each(function() {
// Escape characters used in regex
search_regex.push(jQuery(this).val().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"));
});
displayFilteredColumnNames();
if (search_regex.length === 0) {
annotationsTable.fnFilter("", BP_COLUMNS.classes);
} else {
annotationsTable.fnFilter("^" + search_regex.join("(?!.)|^") + "(?!.)", BP_COLUMNS.classes, true, false);
}
}
};
var filter_matched_ontologies = {
init: function() {
"use strict";
jQuery("#filter_matched_ontologies").bind("click", function(e) {
bp_popup_init(e);
});
// Need to use bind to avoid "live" propogation issues
jQuery(".filter_matched_ontology_checkboxes").bind("click", function(e) {
filter_matched_ontologies.filter(e);
});
jQuery("#ontology_matched_filter_list").click(function(e) {
e.stopPropagation();
});
this.cleanup();
},
cleanup: function() {
"use strict";
jQuery("html").click(bp_popup_cleanup);
jQuery(document).keyup(function(e) {
if (e.keyCode == 27) {
bp_popup_cleanup();
} // esc
});
},
filter: function(e) {
"use strict";
e.stopPropagation();
var search_regex = [];
jQuery(".filter_matched_ontology_checkboxes:checked").each(function() {
search_regex.push(jQuery(this).val());
});
displayFilteredColumnNames();
if (search_regex.length === 0) {
annotationsTable.fnFilter("", BP_COLUMNS.matched_ontologies);
} else {
annotationsTable.fnFilter(search_regex.join("|"), BP_COLUMNS.matched_ontologies, true, false);
}
}
};
var filter_matched_classes = {
init: function() {
"use strict";
jQuery("#filter_matched_classes").bind("click", function(e) {
bp_popup_init(e)
});
// Need to use bind to avoid "live" propogation issues
jQuery(".filter_matched_classes_checkboxes").bind("click", function(e) {
filter_matched_classes.filter(e)
});
jQuery("#matched_classes_filter_list").click(function(e) {
e.stopPropagation()
});
this.cleanup();
},
cleanup: function() {
"use strict";
jQuery("html").click(bp_popup_cleanup);
jQuery(document).keyup(function(e) {
if (e.keyCode == 27) {
bp_popup_cleanup();
} // esc
});
},
filter: function(e) {
"use strict";
e.stopPropagation();
var search_regex = [];
jQuery(".filter_matched_classes_checkboxes:checked").each(function() {
// Escape characters used in regex
search_regex.push(jQuery(this).val().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"));
});
displayFilteredColumnNames();
if (search_regex.length === 0) {
annotationsTable.fnFilter("", BP_COLUMNS.matched_classes);
} else {
annotationsTable.fnFilter("^" + search_regex.join("(?!.)|^") + "(?!.)", BP_COLUMNS.matched_classes, true, false);
}
}
};
var filter_match_type = {
init: function() {
"use strict";
jQuery("#filter_match_type").bind("click", function(e) {
bp_popup_init(e)
});
// Need to use bind to avoid "live" propogation issues
jQuery(".filter_match_type_checkboxes").bind("click", function(e) {
filter_match_type.filterMatchType(e)
});
jQuery("#match_type_filter_list").click(function(e) {
e.stopPropagation()
});
this.cleanup();
},
cleanup: function() {
"use strict";
jQuery("html").click(bp_popup_cleanup);
jQuery(document).keyup(function(e) {
if (e.keyCode == 27) {
bp_popup_cleanup();
} // esc
});
},
filterMatchType: function(e) {
"use strict";
e.stopPropagation();
var search_regex = [];
jQuery(".filter_match_type_checkboxes:checked").each(function() {
// Escape characters used in regex
search_regex.push(jQuery(this).val().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"));
});
displayFilteredColumnNames();
if (search_regex.length === 0) {
annotationsTable.fnFilter("", BP_COLUMNS.types);
} else {
annotationsTable.fnFilter("^" + search_regex.join("(?!.)|^") + "(?!.)", BP_COLUMNS.types, true, false);
}
}
};
var removeFilters = function() {
"use strict";
jQuery(".filter_ontology_checkboxes").attr("checked", false);
jQuery(".filter_classes_checkboxes").attr("checked", false);
jQuery(".filter_match_type_checkboxes").attr("checked", false);
jQuery(".filter_matched_classes_checkboxes").attr("checked", false);
jQuery(".filter_matched_ontologies_checkboxes").attr("checked", false);
annotationsTable.fnFilter("", BP_COLUMNS.classes);
annotationsTable.fnFilter("", BP_COLUMNS.ontologies);
annotationsTable.fnFilter("", BP_COLUMNS.types);
annotationsTable.fnFilter("", BP_COLUMNS.matched_classes);
annotationsTable.fnFilter("", BP_COLUMNS.matched_ontologies);
jQuery("#filter_list").hide();
};
// Datatables reset sort extension
jQuery.fn.dataTableExt.oApi.fnSortNeutral = function(oSettings) {
"use strict";
/* Remove any current sorting */
oSettings.aaSorting = [];
/* Sort display arrays so we get them in numerical order */
oSettings.aiDisplay.sort(function(x, y) {
return x - y;
});
oSettings.aiDisplayMaster.sort(function(x, y) {
return x - y;
});
/* Redraw */
oSettings.oApi._fnReDraw(oSettings);
};
function annotatorFormatLink(param_string, format) {
"use strict";
// TODO: Check whether 'text' and 'tabDelimited' could work.
// For now, assume that json and xml will work or should work.
var format_map = {
"json": "JSON",
"rdf": "RDF",
"xml": "XML",
"text": "Text",
"tabDelimited": "CSV",
"quaero": "QUAERO",
"brat": "BRAT"
};
var query = BP_CONFIG.proxy_url + "/annotatorplus?apikey=" + BP_CONFIG.apikey + "&" + param_string;
if (format !== 'json') {
query += "&format=" + format;
}
// var link = "<a href=\"" + encodeURI(query) + "\" class=\"btn btn-default btn-sm\" target=\"_blank\">" + format_map[format] + "</a>";
var link = "<a href=\"" + encodeURI(query) + "\" class = \"btn btn-outline-primary btn-sm\" target=\"_blank\">" + format_map[format] + "</a>";
jQuery("#download_links_" + format.toLowerCase()).html(link);
}
function generateParameters() {
"use strict";
var params = [];
var new_params = jQuery.extend(true, {}, bp_last_params); // deep copy
delete new_params["apikey"];
delete new_params["format"];
delete new_params["raw"];
//console.log(new_params);
jQuery.each(new_params, function(k, v) {
if (v !== null && v !== undefined) {
if (typeof v == "boolean") {
params.push(k + "=" + v);
} else if (typeof v == "string" && v.length > 0) {
params.push(k + "=" + v);
} else if (typeof v == "array" && v.length > 0) {
params.push(k + "=" + v.join(','));
} else if (typeof v == "object" && v.length > 0) {
params.push(k + "=" + v.join(','));
}
}
});
return params.join("&");
}
jQuery(document).ready(function() {
"use strict";
jQuery("#annotator_button").click(get_annotations);
jQuery("#semantic_types").select2({
allowClear: true,
dropdownParent: jQuery(".annotatorplus form")
});
jQuery("#semantic_groups").select2({
allowClear: true,
dropdownParent: jQuery(".annotatorplus form")
});
jQuery("#ontology_ontologyId").select2({
allowClear: true,
dropdownParent: jQuery(".annotatorplus form")
});
jQuery("#insert_text_link").click(insertSampleText);
jQuery("#advancedOptionsLink").click(toggle_advanced_options);
jQuery("#advanced-options-container").hide();
// Init annotation table
annotationsTable = jQuery("#annotations").dataTable({
bPaginate: false,
bAutoWidth: false,
aaSorting: [],
oLanguage: {
sZeroRecords: "No annotations found"
},
"aoColumns": [{
// Class column
"sWidth": "15%"
}, {
// Ontology column
"sWidth": "15%"
}, {
// Type column
"sWidth": "5%"
}, {
// column not displayed
"sWidth": "5%",
"bVisible": false
}, {
// Context column
"sWidth": "20%"
}, {
// Matched class column
"sWidth": "15%"
}, {
// matchedOntology column
"sWidth": "15%"
}, {
// Score column
"sWidth": "5%",
"bVisible": false
}, {
// Negation column
"sWidth": "5%",
"bVisible": false
}, {
// Experiencer column
"sWidth": "5%",
"bVisible": false
}, {
// Temporality column
"sWidth": "5%",
"bVisible": false
}]
});
filter_ontologies.init();
filter_classes.init();
filter_match_type.init();
filter_matched_ontologies.init();
filter_matched_classes.init();
jQuery("#annotator-help").on("click", bpPopWindow);
jQuery("#annotations_container").hide();
}); // doc ready
function get_link(uri, label) {
"use strict";
return '<a href="' + uri + '">' + label + '</a>';
}
function get_class_details(cls) {
var
cls_rel_ui = cls.ui.replace(/^.*\/\/[^\/]+/, ''),
ont_rel_ui = cls_rel_ui.replace(/\?p=classes.*$/, '?p=summary');
return class_details = {
cls_rel_ui: cls_rel_ui,
ont_rel_ui: ont_rel_ui,
cls_link: get_link(cls_rel_ui, cls.prefLabel),
ont_link: get_link(ont_rel_ui, cls.ontology.name),
semantic_types: cls.semantic_types.join('; ') // test with 'abscess' text and sem type = T046,T020
}
}
function get_class_details_from_raw(cls) {
var
ont_acronym = cls.links.ontology.replace(/.*\//, ''),
ont_name = annotator_ontologies[cls.links.ontology].name,
ont_rel_ui = '/ontologies/' + ont_acronym,
ont_link = null;
if (ont_name === undefined) {
ont_link = get_link_for_ont_ajax(ont_acronym);
} else {
ont_link = get_link(ont_rel_ui, ont_name); // no ajax required!
}
var
cls_rel_ui = cls.links.ui.replace(/^.*\/\/[^\/]+/, ''),
cls_label = cls.prefLabel,
cls_link = null;
if (cls_label === undefined) {
cls_link = get_link_for_cls_ajax(cls['@id'], ont_acronym);
} else {
cls_link = get_link(cls_rel_ui, cls_label); // no ajax required!
}
return class_details = {
cls_rel_ui: cls_rel_ui,
ont_rel_ui: ont_rel_ui,
cls_link: cls_link,
ont_link: ont_link,
//
// TODO: Get semantic types from raw data, currently provided by controller.
//semantic_types: cls.semantic_types.join('; ') // test with 'abscess' text and sem type = T046,T020
semantic_types: ''
}
}
function get_text_markup(text, from, to) {
var
text_match = text.substring(from - 1, to),
// remove everything prior to the preceding three words (using space delimiters):
text_prefix = text.substring(0, from - 1).replace(/.* ((?:[^ ]* ){2}[^ ]*$)/, "... $1"),
// remove the fourth space and everything following it
text_suffix = text.substring(to).replace(/^((?:[^ ]* ){3}[^ ]*) [\S\s]*/, "$1 ..."),
match_span = '<span style="color: rgb(153,153,153);">',
match_markup_span = '<span style="color: rgb(35, 73, 121); font-weight: bold; padding: 2px 0px;">',
text_markup = match_markup_span + text_match + "</span>";
//console.log('text markup: ' + text_markup);
return match_span + text_prefix + text_markup + text_suffix + "</span>";
}
function get_annotation_rows(annotation, params) {
"use strict";
// data independent var declarations
var
rows = [],
cells = [],
text_markup = '',
match_type = '',
match_type_translation = {
"mgrep": "direct",
"mapping": "mapping",
"closure": "ancestor"
};
// data dependent var declarations
var cls = get_class_details(annotation.annotatedClass);
jQuery.each(annotation.annotations, function(i, a) {
text_markup = get_text_markup(params.text, a.from, a.to);
match_type = match_type_translation[a.matchType.toLowerCase()] || 'direct';
cells = [cls.cls_link, cls.ont_link, match_type, cls.semantic_types, text_markup, cls.cls_link, cls.ont_link];
rows.push(cells);
// Add rows for any classes in the hierarchy.
match_type = 'ancestor';
var h_c = null;
jQuery.each(annotation.hierarchy, function(i, h) {
h_c = get_class_details(h.annotatedClass);
cells = [h_c.cls_link, h_c.ont_link, match_type, cls.semantic_types, text_markup, cls.cls_link, cls.ont_link];
rows.push(cells);
}); // hierarchy loop
// Add rows for any classes in the mappings. Note the ont_link will be different.
match_type = 'mapping';
var m_c = null;
jQuery.each(annotation.mappings, function(i, m) {
m_c = get_class_details(m.annotatedClass);
cells = [m_c.cls_link, m_c.ont_link, match_type, cls.semantic_types, text_markup, cls.cls_link, cls.ont_link];
rows.push(cells);
}); // mappings loop
}); // annotations loop
return rows;
}
function get_annotation_score(cls) {
var score = '';
if (typeof cls.score !== 'undefined') {
score = parseFloat(cls.score).toFixed(3);
}
return score;
}
/**
* Set context value (negation, temporality or experienced) to empty string to avoid useless dataTable warning
* @param context
* @returns {*}
*/
function get_context_value(context) {
if (typeof context === 'undefined') {
return '';
}
return context;
}
function get_annotation_rows_from_raw(annotation, params) {
"use strict";
// data independent var declarations
var
rows = [],
cells = [],
text_markup = '',
match_type = '',
match_type_translation = {
"mgrep": "direct",
"mapping": "mapping",
"closure": "ancestor"
};
// data dependent var declarations
var cls = get_class_details_from_raw(annotation.annotatedClass);
if (annotation.annotations.length == 0) {
cells = [cls.cls_link, cls.ont_link, "", cls.semantic_types, "", cls.cls_link, cls.ont_link, get_annotation_score(annotation)];
rows.push(cells);
} else {
jQuery.each(annotation.annotations, function(i, a) {
text_markup = get_text_markup(params.text, a.from, a.to);
match_type = match_type_translation[a.matchType.toLowerCase()] || 'direct';
cells = [cls.cls_link, cls.ont_link, match_type, cls.semantic_types, text_markup, cls.cls_link, cls.ont_link, get_annotation_score(annotation), get_context_value(a.negationContext), get_context_value(a.experiencerContext), get_context_value(a.temporalityContext)];
rows.push(cells);
// Add rows for any classes in the hierarchy.
match_type = 'ancestor';
var h_c = null;
jQuery.each(annotation.hierarchy, function(i, h) {
h_c = get_class_details_from_raw(h.annotatedClass);
cells = [h_c.cls_link, h_c.ont_link, match_type, cls.semantic_types, text_markup, cls.cls_link, cls.ont_link, get_annotation_score(h), get_context_value(a.negationContext), get_context_value(a.experiencerContext), get_context_value(a.temporalityContext)];
rows.push(cells);
}); // hierarchy loop
// Add rows for any classes in the mappings. Note the ont_link will be different.
match_type = 'mapping';
var m_c = null;
jQuery.each(annotation.mappings, function(i, m) {
m_c = get_class_details_from_raw(m.annotatedClass);
cells = [m_c.cls_link, m_c.ont_link, match_type, cls.semantic_types, text_markup, cls.cls_link, cls.ont_link, get_annotation_score(m), get_context_value(a.negationContext), get_context_value(a.experiencerContext), get_context_value(a.temporalityContext)];
rows.push(cells);
}); // mappings loop
}); // annotations loop
}
return rows;
}
function update_annotations_table(rowsArray) {
"use strict";
var ontologies = {},
classes = {},
match_types = {},
matched_ontologies = {},
matched_classes = {},
context_count = 0;
jQuery(rowsArray).each(function() {
// [ cls_link, ont_link, match_type, semantic_types, text_markup, cls_link, ont_link ];
var row = this,
cls_link = row[0],
ont_link = row[1],
match_type = row[2], // direct, ancestors, mapping
//semantic_type = row[3],
//match_text = row[4],
match_cls_link = row[5],
match_ont_link = row[6];
// Extract labels from links (using non-greedy regex).
var cls_label = cls_link.replace(/^<a.*?>/, '').replace('</a>', '').toLowerCase(),
ont_label = ont_link.replace(/^<a.*?>/, '').replace('</a>', ''),
match_cls_label = match_cls_link.replace(/^<a.*?>/, '').replace('</a>', '').toLowerCase(),
match_ont_label = match_ont_link.replace(/^<a.*?>/, '').replace('</a>', '');
// TODO: Gather sem types for display
// var semantic_types = [];
// jQuery.each(annotation.concept.semantic_types, function () {
// semantic_types.push(this.description);
// });
// Keep track of contexts. If there are none (IE when using mallet), hide the column
if (row[4] !== "") context_count++;
// Keep track of how many results are associated with each ontology
ontologies[ont_label] = (ont_label in ontologies) ? ontologies[ont_label] + 1 : 1;
// Keep track of how many results are associated with each class
classes[cls_label] = (cls_label in classes) ? classes[cls_label] + 1 : 1;
// Keep track of match types
match_types[match_type] = (match_type in match_types) ? match_types[match_type] + 1 : 1;
// Keep track of matched classes
matched_classes[match_cls_label] = (match_cls_label in matched_classes) ? matched_classes[match_cls_label] + 1 : 1;
// Keep track of matched ontologies
matched_ontologies[match_ont_label] = (match_ont_label in matched_ontologies) ? matched_ontologies[match_ont_label] + 1 : 1;
});
// Add result counts
var count_span = '<span class="result_count">'
jQuery("#result_counts").html("total results " + count_span + rowsArray.length + "</span> ");
var direct_count = ("direct" in match_types) ? match_types["direct"] : 0,
ancestor_count = ("ancestor" in match_types) ? match_types["ancestor"] : 0,
mapping_count = ("mapping" in match_types) ? match_types["mapping"] : 0;
jQuery("#result_counts").append("(");
jQuery("#result_counts").append("direct " + count_span + direct_count + "</span>");
jQuery("#result_counts").append(" / " + "ancestor " + count_span + ancestor_count + "</span>");
jQuery("#result_counts").append(" / " + "mapping " + count_span + mapping_count + "</span>");
jQuery("#result_counts").append(")");
// Add checkboxes to filters
createFilterCheckboxes(ontologies, "filter_ontology_checkboxes", "ontology_filter_list");
createFilterCheckboxes(classes, "filter_classes_checkboxes", "classes_filter_list");
createFilterCheckboxes(match_types, "filter_match_type_checkboxes", "match_type_filter_list");
createFilterCheckboxes(matched_ontologies, "filter_matched_ontology_checkboxes", "matched_ontology_filter_list");
createFilterCheckboxes(matched_classes, "filter_matched_classes_checkboxes", "matched_classes_filter_list");
// Reset table
annotationsTable.fnClearTable();
annotationsTable.fnSortNeutral();
removeFilters();
// Need to re-init because we're not using "live" because of propagation issues
filter_ontologies.init();
filter_classes.init();
filter_match_type.init();
filter_matched_ontologies.init();
filter_matched_classes.init();
// Add data
if (rowsArray.length > 0) {
annotationsTable.fnAddData(rowsArray);
}
// Hide columns as necessary
if (context_count == 0) {
annotationsTable.fnSetColumnVis(4, false);
} else {
annotationsTable.fnSetColumnVis(4, true);
}
var match_keys = Object.keys(match_types);
if (match_keys.length == 1 && match_keys[0] === "")
annotationsTable.fnSetColumnVis(2, false);
}
function display_annotations(data, params) {
"use strict";
var annotations = data.annotations;
var all_rows = [];
if (params.raw !== undefined && params.raw === true) {
// The annotator_controller does not 'massage' the REST data.
// The class prefLabel and ontology name must be resolved with ajax.
annotator_ontologies = data.ontologies;
for (var i = 0; i < annotations.length; i++) {
all_rows = all_rows.concat(get_annotation_rows_from_raw(annotations[i], params));
}
} else {
// The annotator_controller does 'massage' the REST data.
// The class prefLabel and ontology name get resoled with a batch all in the controller.
for (var i = 0; i < annotations.length; i++) {
all_rows = all_rows.concat(get_annotation_rows(annotations[i], params));
}
}
update_annotations_table(all_rows);
// Generate parameters for list at bottom of page
var param_string = generateParameters(); // uses bp_last_param
var query = BP_CONFIG.proxy_url + "/annotatorplus?" + param_string + "&display_links=false&display_context=false";
var query_encoded = BP_CONFIG.proxy_url + "/annotatorplus?" + encodeURIComponent(param_string);
jQuery("#annotator_parameters").html("<a href=\"" + encodeURI(query) + "\" target=\"_blank\">corresponding REST API call</a>");
jQuery("#annotator_parameters_encoded").html(query_encoded);
// Add links for downloading results
//annotatorFormatLink("tabDelimited");
annotatorFormatLink(param_string, "json");
annotatorFormatLink(param_string, "xml");
annotatorFormatLink(param_string, "brat");
annotatorFormatLink(param_string, "quaero");
annotatorFormatLink(param_string, "rdf");
if (params.raw !== undefined && params.raw === true) {
// Initiate ajax calls to resolve class ID to prefLabel and ontology acronym to name.
ajax_process_init(); // see bp_ajax_controller.js
}
}
function toggle_advanced_options() {
$("#advanced-options-container").toggle();
var text = $("#advanced-options-container").is(':visible') ? "Hide advanced options <<" : "Show advanced options >>";
$("#advancedOptionsLink").text(text);
}
// Creates an HTML form with a button that will POST to the annotator
//function annotatorPostForm(format) {
// "use strict";
// // TODO: Check whether 'text' and 'tabDelimited' could work.
// // For now, assume that json and xml will work or should work.
// var format_map = { "json": "JSON", "xml": "XML", "text": "Text", "tabDelimited": "CSV" };
// var params = bp_last_params;
// params["format"] = format;
// var form_fields = [];
// jQuery.each(params, function (k, v) {
// if (v != null) {
// form_fields.push("<input type='hidden' name='" + k + "' value='" + v + "'>");
// }
// });
// var action = "action='" + BP_CONFIG.rest_url + "/annotator'";
// var form = jQuery("<form " + action + " method='post' target='_blank'/>")
// .append(form_fields.join(""))
// .append("<input type='submit' value='" + format_map[format] + "'>");
// jQuery("#download_links_" + format.toLowerCase()).html(form);
//}