Discovery workout

Get Started

7 juillet 2024

Animators

Olivier FILANGI
Software engineer
Discovery’s creator

Marcellino PALERME
Software assistant engineer

RCA team

Sources

Workout

  • https://github.com/p2m2/DiscoveryWorkout

Tool

  • https://github.com/p2m2/Discovery
  • https://p2m2.github.io/discovery/

Discovery

what is it ?

a software library which aims to ease the development of decision support tools exploiting omics RDF databases.

Integration

  • HTML
<script 
  type="text/javascript" 
  src="https://cdn.jsdelivr.net/gh/p2m2/discovery@0.4.3/dist/discovery-web.min.js"> 
</script> 
  • NPM package
    • Install
    npm install @p2m2/discovery@0.2.0
    • Use
    require("@p2m2/discovery");

Integration

  • HTML
<script 
  type="text/javascript" 
  src="https://cdn.jsdelivr.net/gh/p2m2/discovery@0.4.3/dist/discovery-web.min.js"> 
</script> 

Vim The editor https://www.vim.org

browser( www.teltarif.de

Count Ressouce

Goal

Subject

predicate

Object

Each part of triple is a ressource.

We want to know how many ressources we have.

Code

  • Javascript
var config = SWDiscoveryConfiguration
 .init()
 .urlFile(`https://raw.githubusercontent.com/p2m2/tp-discovery-websempilot/
           main/rdf/triples_assos_CHEBI_MESH_sub.ttl`);

SWDiscovery(config)
    .something("some")
    .select("some")
        .commit()
        .raw()
        .then((response) => {
            // Show number of triple
            isOk("count: "+response.results.bindings.length)
            }
      ).catch( (error) => {
        console.error(" -- catch exception --")
        isKo(error)
      } );

Execute


Exercice

  • Count ressources of CID RDF Database.
    • https://raw.githubusercontent.com/p2m2/tp-discovery-websempilot/main/rdf/triples_assos_CID_MESH_sub.ttl
    • In variable “allRessources”

Solution

var config = SWDiscoveryConfiguration
 .init()
 .urlFile(`https://raw.githubusercontent.com/p2m2/tp-discovery-websempilot/
           main/rdf/triples_assos_CID_MESH_sub.ttl`);

SWDiscovery(config)
  .something("allRessources")
  .select("allRessources")
      .commit()
      .raw()
      .then((response) => {
          // Show number of triple
          isOk("count:"+response.results.bindings.length)
      }
      ).catch( (error) => {
        isKo(error)
      });

Get Object

Goal

Subject

predicate

Object

Find all objects is related with hydroxyoctanoate (ChEBI ID = CHEBI:133719)

Code

-JS

SWDiscovery(config)
    .prefix("chebi","http://purl.obolibrary.org/obo/CHEBI_")
    .prefix("skos","http://www.w3.org/2004/02/skos/core#")
    .something("some")
       .set(URI("chebi:133719"))
         .isSubjectOf(URI("skos:related"),"objetMeshTerm")
    .select("objetMeshTerm")
    .commit()
    .raw()
    .then((response) => {
        message = "<p>termes mesh associés à chebi:133719 ->"+response.results.bindings.length + "</p><ul>" ;
        for (const binding of response.results.bindings) {
            message +=`<li> ${binding["objetMeshTerm"].value} </li>`;
        }
        message += "</ul>"
        isOK(message);

Execute


Exercice

  • Get all compounds related to “Acid, Acyclic” in CID RDF database
    • “Acid, Acyclic” => mesh term http://id.nlm.nih.gov/mesh/D000144
    • isObjectOf

Solution

SWDiscovery(config)
    .prefix("mesh","http://id.nlm.nih.gov/mesh/")
    .prefix("skos","http://www.w3.org/2004/02/skos/core#")
    .something("some")
       .set(URI("mesh:D000144"))
         .isObjectOf(URI("skos:related"),"compounds")
    .select("compounds")
    .commit()
    .raw()
    .then((response) => {
        message = "<p>Suject related mesh D000144 ->"+response.results.bindings.length + "</p><ul>" ;
        for (const binding of response.results.bindings) {
            message +=`<li> ${binding["compounds"].value} </li>`;
        }
        message += "</ul>"
        isOK(message);

Datatype

Goal

  • Send request to sparql endpoint
  • Know caracteristic of a ressources (literal)

Code

  • JavaScript
var config = SWDiscoveryConfiguration
    .init()
    .sparqlEndpoint("https://metabolights.semantic-metabolomics.fr/sparql");

SWDiscovery(config)
    .prefix("metabolights","https://www.ebi.ac.uk/metabolights/property#")
    .prefix("rdfs","http://www.w3.org/2000/01/rdf-schema#")
    .something()
        .isObjectOf(URI("metabolights:Xref"),"var_study")
            .datatype(URI("rdfs:label"),"var_label")
    .select("var_study", "var_label")
        .commit()
        .raw()
    .then((response)=>{
        let message = "<ul>"
        for (let i=0;i<response.results.bindings.length;i++) {
            let study=response.results.bindings[i]["var_study"].value;
            let label=response.results.datatypes["var_label"][study][0].value; 
            message +=`<li> ${study} is ${label}</li>`;
        }
        message += "</ul>"
        isOK(message);
    })

Execute


Exercice

  • Use sparql endpoint of FORUM (https://forum.semantic-metabolomics.fr/sparql/)
  • Get information on chebi:27732
    • Synonym (http://purl.obolibrary.org/obo/chebi/formula)
    • Formula (http://www.geneontology.org/formats/oboInOwl#hasExactSynonym)

Solution

var config = SWDiscoveryConfiguration
  .init()
  .sparqlEndpoint("https://forum.semantic-metabolomics.fr/sparql/");

SWDiscovery(config)
  .prefix("chebi","http://purl.obolibrary.org/obo/CHEBI_")
  .something("var_study")
    .set(URI("chebi:27732"))
      .datatype(URI("http://purl.obolibrary.org/obo/chebi/formula"),"var_formula")
      .datatype(URI("http://www.geneontology.org/formats/oboInOwl#hasExactSynonym"),"var_name")
  .select("var_study", "var_formula", "var_name")
    .commit()
    .raw()
  .then((response)=>{
    let study=response.results.bindings[0]["var_study"].value;
    let formula=response.results.datatypes["var_formula"][study][0].value; 
    let name = response.results.datatypes["var_name"][study][0].value;
    isOK(`${name} : #Ref -> ${study}  #Formula -> ${formula}`);
  })

UX

GOAL

  • Increase UX
    • Display first part of query and waiting all results

long query

Code

var config = SWDiscoveryConfiguration
    .init()
    .setPageSize(rowsPerPage)
    .sparqlEndpoint("https://forum.semantic-metabolomics.fr/sparql/");

SWDiscovery(config)
    .something()
        // Request
    .selectByPage("var")
    .then(async (response)=>{
        nbPages = Object.values(response)[0]
        lazyLoadedPages = Object.values(response)[1]
        load(0)
    })

function load(indexPage){
    if(dataQuery[indexPage] != undefined){
        render(dataQuery[indexPage]);
        return;
    }
    lazyLoadedPages[indexPage]
    .progression( (percent) => {
        progressBar.textContent = percent*100 + '%';
    })
    .requestEvent( (event) => {
        messageElement.textContent = event;
    })
    .commit()
    .raw()
    .then((response) => {
        for (let i=0;i<response.results.bindings.length;i++) {
            dataQuery.push(response.results.bindings[i]["var_subject"].value)
        }
        render(dataQuery[indexPage]);
        return;
    })
}

Exercice

  • Get all subject with predicate : http://www.geneontology.org/formats/oboInOwl#inSubset
  • Get formula of subject: http://purl.obolibrary.org/obo/chebi/formula
  • Get mass of subject: http://purl.obolibrary.org/obo/chebi/mass
  • (option) Get id of subject: http://www.geneontology.org/formats/oboInOwl#id

Solution

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>UX</title>

<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/p2m2/discovery@0.4.3/dist/discovery-web.min.js"> </script> 
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">

<style>
.progress-bar {
            width: 0;
            height: 30px;
            background-color: #4caf50;
            border-radius: 5px;
            text-align: center;
            line-height: 30px;
            color: white;
        }
</style>
<body>

  <div id="icon-container">
      <i id="status-icon" class="icon fas fa-spinner fa-spin"></i>
  </div>
  
  <div id="status-message"></div>

  <h1>Resultats</h1>
  <div class="progress-container">
    <div class="progress-bar" id="progress-bar">0%</div>
  </div>

  <div id="data-container"></div>
<nav>
    <button onclick="load(currentPage-1)">Prev.</button> 
    <button onclick="load(currentPage+1)">Next</button> 
</nav>

</body>

<script>
const showData = document.getElementById('data-container');
const messageElement = document.getElementById('status-message');
const rowsPerPage = 5;
let currentPage = 0;
let lazyLoadedPages = [];
let nbPages = 0 ;
let dataQuery = []; 
var config = SWDiscoveryConfiguration
    .init()
    .setPageSize(rowsPerPage)
    .sparqlEndpoint("https://forum.semantic-metabolomics.fr/sparql/");

SWDiscovery(config)
    .something()
        .isObjectOf(URI("http://www.geneontology.org/formats/oboInOwl#inSubset"), "var_subject")
            .datatype(URI("http://purl.obolibrary.org/obo/chebi/formula"),"var_formula")
            .datatype(URI("http://purl.obolibrary.org/obo/chebi/mass"),"var_mass")
            .datatype(URI("http://www.geneontology.org/formats/oboInOwl#id"), "var_id")
    .selectByPage("var_subject", "var_formula", "var_mass", "var_id")
    .then(async (response)=>{
        nbPages = Object.values(response)[0]
        lazyLoadedPages = Object.values(response)[1]
        isOK("ready");
        load(0);
    })



async function render(data) {
    var html = '<ul>';
    data.forEach((item) => {
        html += `<li>${item.id}: FORM->${item.form} MASS-> ${item.mass}</li>` 
    })
    html += '</ul>';
    showData.innerHTML = html
}

function load(indexPage){
    if(indexPage < 0 || indexPage == nbPages){
        return;
    }
    currentPage = indexPage
    if(dataQuery[indexPage] != undefined)
    {
        render(dataQuery[indexPage]);
        return;
    }
    lazyLoadedPages[indexPage]
        .progression( (percent) => {
            let progressBar = document.getElementById('progress-bar');
            progressBar.style.width = percent*100 + '%';
            progressBar.textContent = percent*100 + '%';
        })
        .requestEvent( (event) => {
            messageElement.textContent = event;
            messageElement.style.color = 'blue';
        })
        .commit()
        .raw()
        .then((response) => {
            const result = []
            for (let i=0;i<response.results.bindings.length;i++) {
                let ref=response.results.bindings[i]["var_subject"].value;
                let formula=" ";
                if(response.results.datatypes["var_formula"][ref]!=undefined){
                    formula = response.results.datatypes["var_formula"][ref][0].value;
                }
                
                let mass = " ";
                if(response.results.datatypes["var_mass"][ref]!=undefined){
                    mass = response.results.datatypes["var_mass"][ref][0].value;
                }
                let id = " ";
                if(response.results.datatypes["var_id"][ref]!=undefined){
                    id = response.results.datatypes["var_id"][ref][0].value;
                }
                    result.push({id:id, mass:mass, form:formula});       
            }
            dataQuery.push(result);
            render(result);
        })
}


function isOK(message){
    const iconElement = document.getElementById('status-icon');
    const messageElement = document.getElementById('status-message');
    iconElement.className = 'icon fas fa-check-circle';
    iconElement.style.color = 'green';
    messageElement.innerHTML = message;
    messageElement.style.color = 'green';
}

function isKO(error){
    const iconElement = document.getElementById('status-icon');
    const messageElement = document.getElementById('status-message');
    iconElement.className = 'icon fas fa-times-circle';
    iconElement.style.color = 'red';
    messageElement.textContent = error.message;
    messageElement.style.color = 'red';
}
</script>
</html>    

Serialize and deserialize

Goal

Share result of request

Code - serialize

 var config = SWDiscoveryConfiguration
    .init()
    .rdfContent(`
    @prefix mesh: <http://id.nlm.nih.gov/mesh/> .
    mesh:D005227 <http://myapp/is_selected> true .
    mesh:D002332 <http://myapp/is_selected> true .
    mesh:D005502 <http://myapp/is_selected> true .
    mesh:D009414 <http://myapp/is_selected> true .
    mesh:D009416 <http://myapp/is_selected> true .
    mesh:D009420 <http://myapp/is_selected> true .
    mesh:D009422 <http://myapp/is_selected> true .
    mesh:D009424 <http://myapp/is_selected> true .
    mesh:D009431 <http://myapp/is_selected> true .
    `)
    .urlFile("https://raw.githubusercontent.com/p2m2/tp-discovery-websempilot/main/rdf/triples_assos_CHEBI_MESH_sub.ttl")
    .urlFile("https://raw.githubusercontent.com/p2m2/tp-discovery-websempilot/main/rdf/triples_assos_MESH_MESH_sub.ttl")
    .urlFile("https://raw.githubusercontent.com/p2m2/tp-discovery-websempilot/main/rdf/triples_assos_CID_MESH_sub.ttl")
    ;
   
messageElement.textContent =encodeURIComponent(
    SWDiscovery(config)
        .prefix("chebi","http://purl.obolibrary.org/obo/CHEBI_")
        .prefix("skos","http://www.w3.org/2004/02/skos/core#")
        .something("metabolite")
            .setDecoration("info","Metabolites qui sont reliés à mesh:D005227")
            .isSubjectOf(URI("skos:related"),"objetMeshTerm")
            .isSubjectOf(URI("<http://myapp/is_selected>"))
                .set(Literal("true",URI("xsd:boolean")))
                .getSerializedString());

Execution

Code - deserialize

let str = decodeURIComponent(`%7B%22config%22%3A%7B%22source ....`);
let objDiscovery = SWDiscovery().setSerializedString(str)
let info_metabolite = objDiscovery.focus("metabolite").getDecoration("info");
objDiscovery
    .select("metabolite","objetMeshTerm")
        .commit()
        .raw()
        .then((response) => {
            // process on results

Execution

Help and request

Goal

  • Know called methods of ressources
  • Explain and obtain sparql request

Code

.something("some")
   .set(URI("chebi:133719"))
      .helper();
      .isSubjectOf(URI("skos:related"),"objetMeshTerm")
      .console()      

sample

Your attention is appreciated

Any questions ?