From 45a1d118aee923a279bddf57574ea9dd000d2541 Mon Sep 17 00:00:00 2001 From: "chia-lin.lin" Date: Wed, 13 Dec 2023 09:46:51 +0100 Subject: [PATCH 1/2] 1. Resolved the script error: SyntaxError: undefined is not valid JSON. 2. Used OLS4. --- OntologySearch.gs | 4 ++-- Utils.gs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OntologySearch.gs b/OntologySearch.gs index e3a6824..7010d64 100644 --- a/OntologySearch.gs +++ b/OntologySearch.gs @@ -251,7 +251,7 @@ function searchOLS(term) { ontologyDict[ontologyLabel] = {"ontology-name": elem.ontology_name, "terms": []}; record = { label: elem.label, - id: elem.id, + id: elem.short_form, 'ontology-label': elem.ontology_prefix, 'ontology-name': elem.ontology_name, accession: elem.iri,//elem.obo_id, @@ -293,7 +293,7 @@ function handleTermInsertion(term_id) { // figure out whether the Term Source REF and Term Accession Number columns exist, if they do exist at all. Insertion technique will vary // depending on the file being looked at. var sourceAndAccessionPositions = getSourceAndAccessionPositionsForTerm(selectedRange.getColumn()); - + // add all terms into a separate sheet with all their information. if (sourceAndAccessionPositions.sourceRef != undefined && sourceAndAccessionPositions.accession != undefined) { insertOntologySourceInformationInInvestigationBlock(ontologyObject); diff --git a/Utils.gs b/Utils.gs index f7cfb19..1a69706 100644 --- a/Utils.gs +++ b/Utils.gs @@ -32,7 +32,7 @@ // constants -var OLS_API_BASE_URI = "http://www.ebi.ac.uk/ols/api"; +var OLS_API_BASE_URI = "http://www.ebi.ac.uk/ols4/api"; var OLS_PAGINATION_SIZE = 500; // MAX pagination size /** From 2d18c918ee028356e7391e8013714822904501ae Mon Sep 17 00:00:00 2001 From: "chia-lin.lin" Date: Tue, 2 Jan 2024 10:03:15 +0100 Subject: [PATCH 2/2] Add the tib service as an OLS endpoint to the ontology search function. --- Ontology-Search-Template.html | 23 ++++++------- OntologySearch.gs | 62 ++++++++++++++++++++++++++++++++++- Ontomaton-terms.md | 5 +-- README.md | 26 +++++++-------- Settings.gs | 50 ++++++++++++++++++++++++---- Utils.gs | 3 +- 6 files changed, 134 insertions(+), 35 deletions(-) diff --git a/Ontology-Search-Template.html b/Ontology-Search-Template.html index 5e2f6fa..e85fdca 100644 --- a/Ontology-Search-Template.html +++ b/Ontology-Search-Template.html @@ -29,7 +29,7 @@ .hidden { display: none; } - + .error { padding-top: 10px; color: #e74c3c; @@ -233,6 +233,7 @@ + @@ -302,21 +303,21 @@ * the sidebar UI with the resulting translation. */ function runSearch() { - + var term = $('input[name=search-text]').val(); - + if(term === "") { showError('Please enter a search term.', $('#button-bar')); return } - - this.disabled = true; - + + this.disabled = true; + $('#search-results').html('

Searching...

'); $('#error').remove(); var service = $('#service').val(); - + google.script.run .withSuccessHandler( @@ -325,10 +326,10 @@ var html = '
'; console.log(result); if (result) { - + Object.keys(result).sort().forEach(function(ontology_abbr) { var ontology = result[ontology_abbr]; - + html += '

' + ontology_abbr + ' - ' + ontology["ontology-name"] + '

' + '
    ' @@ -345,10 +346,10 @@ '
    ' + ''; }); - + html += '
'; }); - + } else { html += "

Sorry, no results were found matching your query...

"; } diff --git a/OntologySearch.gs b/OntologySearch.gs index 7010d64..7d16729 100644 --- a/OntologySearch.gs +++ b/OntologySearch.gs @@ -52,6 +52,8 @@ function performSearch(service, term) { return searchLOV(term); case "ols": return searchOLS(term); + case "tib-ols": + return searchTIBOLS(term); default: return searchLOV(term); } @@ -274,6 +276,64 @@ function searchOLS(term) { } } + +/** + * @method + * @name searchTIBOLS + * @param{string} term + */ +function searchTIBOLS(term) { + try { + var restriction = findRestrictionForCurrentColumn("OLS"); + var ontologies = getTIBOLSOntologies(); + var url = TIBOLS_API_BASE_URI + '/search'; + var queryObj = { + q: term, + rows: OLS_PAGINATION_SIZE, + start: 0, + ontology: restriction ? restriction.ontologyId : undefined + }; + var queryString = jsonToQueryString(queryObj); + url += '?' + queryString; + var cacheResult = fetchFromCache(url); + if (cacheResult) { + return JSON.parse(cacheResult); + } + var text = UrlFetchApp.fetch(url).getContentText(), json = JSON.parse(text), ontologyDict = {}; + + var docs = json.response && json.response.docs; + if (!docs || docs.length === 0) { + throw "No Result found."; + } + docs.forEach(function(elem) { + var ontology = ontologies[elem.ontology_name], ontologyLabel = elem.ontology_prefix, record; + if (!ontologyDict[ontologyLabel]) { + ontologyDict[ontologyLabel] = {"ontology-name": elem.ontology_name, "terms": []}; + record = { + label: elem.label, + id: elem.short_form, + 'ontology-label': elem.ontology_prefix, + 'ontology-name': elem.ontology_name, + accession: elem.iri,//elem.obo_id, + ontology: elem.ontology_name, + details: '', + url: elem.iri + }; + + storeInCache(record.id, JSON.stringify(record)); + ontologyDict[ontologyLabel].terms.push(record); + } + }); + storeInCache(url, JSON.stringify(ontologyDict)); + // Logger.log(ontologyDict); + return ontologyDict; + } + catch(e) { + Logger.log(e); + throw(e); + } +} + function handleTermInsertion(term_id) { try { var sheet = SpreadsheetApp.getActiveSheet(); @@ -328,4 +388,4 @@ function handleTermInsertion(term_id) { throw err; } -} \ No newline at end of file +} diff --git a/Ontomaton-terms.md b/Ontomaton-terms.md index 0b6d160..bdb3ed0 100644 --- a/Ontomaton-terms.md +++ b/Ontomaton-terms.md @@ -13,6 +13,7 @@
  • NBCO Bioportal
  • EMBL-EBI Ontology Lookup Service
  • Linked Open Vocabularies catalogue
  • +
  • TIB Terminology Service
  • @@ -30,11 +31,11 @@ Bioinformatics 2013 29: 525-527. Bioinformatics article on OntoMaton [here](http://dx.doi.org/10.1093/bioinformatics/bts718). -Eamonn Maguire, Alejandra González-Beltrán, Patricia L. Whetzel, Susanna-Assunta Sansone, and Philippe Rocca-Serra -OntoMaton: a Bioportal powered ontology widget for Google Spreadsheets +Eamonn Maguire, Alejandra González-Beltrán, Patricia L. Whetzel, Susanna-Assunta Sansone, and Philippe Rocca-Serra +OntoMaton: a Bioportal powered ontology widget for Google Spreadsheets Bioinformatics 2013 29: 525-527. doi: [10.1093/bioinformatics/bts718](http://dx.doi.org/10.1093/bioinformatics/bts718) Please, note that at the time of the publication, OntoMaton was powered by the NCBO BioPortal web services. Since then, we have made the following extensions: - we upgraded the code to [Google Add-ons for Docs and Sheets](http://googledrive.blogspot.it/2014/03/add-ons.html), which [deprecated the Apps Script applications and the Script Gallery](http://googleappsdeveloper.blogspot.co.uk/2014/06/deprecating-script-gallery-in-old.html), used in the original OntoMaton version - we upgraded to the new BioPortal API for searching ontology terms and annotator services (see BioPortal 4.0 release notes), as the old API was deprecated in 2014 -- we extended the ontology search functionality to support REST services from the Linked Open Vocabularies and the EBI Ontology Lookup Service, thus now allowing ontology term searches over three separate services. +- we extended the ontology search functionality to support REST services from the Linked Open Vocabularies, the EBI Ontology Lookup Service, and the TIB Terminology Service, thus now allowing ontology term searches over three separate services. -For more information, see [our blog posts on OntoMaton](https://isatools.wordpress.com/?s=ontomaton). +For more information, see [our blog posts on OntoMaton](https://isatools.wordpress.com/?s=ontomaton). ### Installation -With the new add on infrastructure, installation is very easy. +With the new add on infrastructure, installation is very easy. 1. Click on the 'Add-ons' menu item in your Google Spreadsheet: @@ -43,7 +43,7 @@ With the new add on infrastructure, installation is very easy.
    -2. Click on 'Get add-ons...' and then search for 'OntoMaton': +2. Click on 'Get add-ons...' and then search for 'OntoMaton':
    @@ -68,7 +68,7 @@ Here you can click on the image and read more about OntoMaton:
    -4. You'll then have the OntoMaton app installed. +4. You'll then have the OntoMaton app installed.
    @@ -90,7 +90,7 @@ From OntoMaton, you can search three different services within one tool: the [NC ### Ontology Tagging -With OntoMaton, you can select a number of spreadsheet cells and then 'tag' them. This means that OntoMaton will take the terms in the cells and send them to BioPortal's Annotator service. The results will come back as a list of the free text terms, showing for each all matches in BioPortal. +With OntoMaton, you can select a number of spreadsheet cells and then 'tag' them. This means that OntoMaton will take the terms in the cells and send them to BioPortal's Annotator service. The results will come back as a list of the free text terms, showing for each all matches in BioPortal.
    @@ -105,8 +105,8 @@ With OntoMaton, you can select a number of spreadsheet cells and then 'tag' them From the settings screen, you can configure: -* How terms should be inserted in to the spreadsheet when not in 'ISA mode' (where the next columns aren't named 'Term Source REF' or 'Term Source Accession'). The two options are as either as a hyperlink to the term in Bioportal/OLS/LOV or as a term name with the hyperlink in parentheses. -* Restrictions, which specify for zero or more columns (with a name in the first cell), restrictions that should be placed on the search space per each of the ontology lookup services we use (Bioportal/OLS/LOV) E.g. the column 'Label' is restricted to terms from the Chemincal Entities of Biomedical Interest ontology (ChEBI). Please, note that for instance if a column has a restriction over the BioPortal service, the restiction will not have an effect if searching terms with OLS. +* How terms should be inserted in to the spreadsheet when not in 'ISA mode' (where the next columns aren't named 'Term Source REF' or 'Term Source Accession'). The two options are as either as a hyperlink to the term in Bioportal/OLS/LOV or as a term name with the hyperlink in parentheses. +* Restrictions, which specify for zero or more columns (with a name in the first cell), restrictions that should be placed on the search space per each of the ontology lookup services we use (Bioportal/OLS/LOV) E.g. the column 'Label' is restricted to terms from the Chemincal Entities of Biomedical Interest ontology (ChEBI). Please, note that for instance if a column has a restriction over the BioPortal service, the restiction will not have an effect if searching terms with OLS. ### Restricting OntoMaton's search space @@ -121,17 +121,17 @@ From the settings screen, you can configure: When you add a restriction using the 'Settings' panel for the first time, a 'Restrictions' sheet will be added automatically. This sheet will have the following column headers: -```Column Name | Ontology | Branch | Version | Ontology Name | Service```. Then you may define for a particular column header in your spreadsheet what ontology should be searched (or list of ontologies) over what service (BioPortal, OLS or LOV). A restriction will only apply if using the corresponding service for search. +```Column Name | Ontology | Branch | Version | Ontology Name | Service```. Then you may define for a particular column header in your spreadsheet what ontology should be searched (or list of ontologies) over what service (BioPortal, OLS or LOV). A restriction will only apply if using the corresponding service for search. Additionally, within one ontology restriction, for BioPortal searches, you can restrict to a particular branch of an ontology, providing a way to further restrict the search space. An example of a google spreadsheet with such functionality can be viewed here: https://docs.google.com/spreadsheet/ccc?key=0Al5WvYyk0zzmdDNLeEcxWHZJX042dS0taXJPNXpJMHc - + ### Video Tutorial Access the video tutorial showing how to install and use OntoMaton (version 1) [here](http://www.youtube.com/watch?v=Qs0nxGBfQac&feature=player_embedded). - + ### Templates Templates can be found through accessing them on the google templates site. OntoMaton templates are [here](https://drive.google.com/templates?type=spreadsheets&q=ontomaton). diff --git a/Settings.gs b/Settings.gs index 1454bc9..5cb7bfa 100644 --- a/Settings.gs +++ b/Settings.gs @@ -38,7 +38,7 @@ function showSettings() { SpreadsheetApp.getUi().showSidebar(html); } -function loadOntologies() { +function loadOntologies() { return { 'BioPortal': getBioPortalOntologies(), 'LOV': getLinkedOpenVocabularies(), @@ -61,8 +61,8 @@ function viewRestrictionHandler() { var restrictionSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Restrictions"); if (restrictionSheet == undefined) { - UiApp.getActiveApplication().getElementById("status").setText("Restriction sheet doesn't exist yet. Add a restriction and it will be created automatically."); - return UiApp.getActiveApplication(); + var htmlOutput = HtmlService.createHtmlOutput("

    Restriction sheet doesn't exist yet. Add a restriction and it will be created automatically.

    "); + SpreadsheetApp.getActiveSpreadsheet().show(htmlOutput); } else { SpreadsheetApp.getActiveSpreadsheet().setActiveSheet(restrictionSheet); } @@ -79,11 +79,11 @@ function loadPreferences() { } function addRestrictionHandler(params) { - + var ontology = params.ontology.trim(); var columnName = params.columnName.trim(); var service = params.service.trim(); - + var restrictionSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Restrictions"); if (restrictionSheet == undefined) { @@ -99,7 +99,7 @@ function addRestrictionHandler(params) { SpreadsheetApp.getActiveSpreadsheet().setActiveSheet(activeSheet); } - + if(columnName !== "") { var nextBlankRow = findNextBlankRow(restrictionSheet); restrictionSheet.getRange(nextBlankRow, 1).setValue(columnName); @@ -108,7 +108,7 @@ function addRestrictionHandler(params) { restrictionSheet.getRange(nextBlankRow, 6).setValue(service); return "Restriction for " + columnName + " Added" } - + return "Column name cannot be empty." } @@ -205,3 +205,39 @@ function getOLSOntologies() { return ontologyDict; } + +/** + * @method + * @name getTIBOLSOntologies + * @description gets all the ontologies from TIB-OLS + * @return{Object} + */ +function getTIBOLSOntologies() { + var ontologiesUri = TIBOLS_API_BASE_URI + "/ontologies?size=" + OLS_PAGINATION_SIZE; + var cache = CacheService.getPrivateCache(), res, text, json, ontologies = []; + + if (cache.get("tib-ols") == null) { + do { + res = UrlFetchApp.fetch(ontologiesUri); + text = res.getContentText('utf-8'); + json = JSON.parse(text); + ontologies = ontologies.concat(json._embedded.ontologies); + ontologiesUri = json._links && json._links.next && json._links.next.href; + } + while (ontologiesUri); + // store into cache the result as plain text + splitResultAndCache(cache, "tib-ols", JSON.stringify(ontologies)); + } else { + ontologies = JSON.parse(getCacheResultAndMerge(cache, "tib-ols")); + } + + var ontologyDict = {}; + ontologies.forEach(function(ontology) { + var config = ontology.config || {}; + ontologyDict[ontology.ontologyId] = { + name: config.title, + uri: config.id + }; + }); + return ontologyDict; +} diff --git a/Utils.gs b/Utils.gs index 1a69706..d8c3bca 100644 --- a/Utils.gs +++ b/Utils.gs @@ -32,6 +32,7 @@ // constants +var TIBOLS_API_BASE_URI = "https://service.tib.eu/ts4tib/api"; var OLS_API_BASE_URI = "http://www.ebi.ac.uk/ols4/api"; var OLS_PAGINATION_SIZE = 500; // MAX pagination size @@ -361,4 +362,4 @@ function replaceControlCharacters(text) { } catch (e){ return text; } -} \ No newline at end of file +}