# Public API for PubSeq import os import requests import sys import types from flask import Flask, request, redirect, send_file, send_from_directory, render_template, jsonify from bh20simplewebuploader.main import app, sparqlURL PUBSEQ="http://covid19.genenetwork.org" ARVADOS="https://collections.lugli.arvadosapi.com/c=" # Helper functions def fetch_sample(id, query=None): default_query = """ PREFIX pubseq: PREFIX sio: PREFIX edam: PREFIX efo: PREFIX evs: PREFIX obo: select distinct ?id ?seq ?date ?info ?specimen ?sequencer ?mapper { ?sample sio:SIO_000115 "%s" ; sio:SIO_000115 ?id ; evs:C25164 ?date . ?seq pubseq:technology ?tech ; pubseq:sample ?sample . optional { ?tech efo:EFO_0002699 ?mapper } . optional { ?tech obo:OBI_0600047 ?sequencer . } optional { ?sample edam:data_2091 ?info } . optional { ?sample obo:OBI_0001479 ?specimen } . } limit 5 """ % id if not query: query = default_query print(query) payload = {'query': query, 'format': 'json'} r = requests.get(sparqlURL, params=payload) res = r.json() print(res) return res['results']['bindings'],res['head']['vars'] def fetch_one_sample(id, query=None): """Get the top sample and return a SimpleNamespace""" result,varlist = fetch_sample(id,query) h = {} row = result[0] for key in varlist: if key in row: h[key] = row[key]['value'] print(h) h['arv_id'] = os.path.basename(h['seq']) return types.SimpleNamespace(**h) def fetch_one_record(id): m = fetch_one_sample(id) arv_id = m.arv_id rec = { "id": id, 'arv_id': arv_id, "permalink": PUBSEQ+'/resource/'+id, "collection": m.seq, 'collection_date': m.date, 'fasta': ARVADOS+arv_id+'/sequence.fasta', 'metadata': ARVADOS+arv_id+'/metadata.yaml', } h = m.__dict__ # for optional items if 'mapper' in h: rec['mapper'] = m.mapper if 'sequencer' in h: rec['sequencer']= m.sequencer return rec # Main API routes @app.route('/api/version') def version(): return jsonify({ 'service': 'PubSeq', 'version': 0.10 }) @app.route('/api/sample/.json') def sample(id): """ API sample should return a record pointing to other resources, notably: permalink, original metadata record and the fasta data. curl http://localhost:5067/api/sample/MT533203.1.json { "id": "MT533203.1", "permalink": "http://covid19.genenetwork.org/resource/MT533203.1", "collection": "http://covid19.genenetwork.org/resource/lugli-4zz18-uovend31hdwa5ks", "collection_date": "2020-04-27", "fasta": "https://collections.lugli.arvadosapi.com/c=lugli-4zz18-uovend31hdwa5ks/sequence.fasta", "metadata": "https://collections.lugli.arvadosapi.com/c=lugli-4zz18-uovend31hdwa5ks/metadata.yaml", "mapper": "minimap v. 2.17", "sequencer": "http://www.ebi.ac.uk/efo/EFO_0008632" } """ return jsonify([fetch_one_record(id)]) @app.route('/api/ebi/sample-.xml', methods=['GET']) def ebi_sample(id): meta,varlist = fetch_sample(id)[0] page = render_template('ebi-sample.xml',sampleid=id,sequencer=meta['sequencer']['value'],date=meta['date']['value'],specimen=meta['specimen']['value']) return page @app.route('/api/search', methods=['GET']) def search(): """ Execute a 'global search'. Currently just duplicates fetch one sample. Should be more flexible FIXME. """ s = request.args.get('s') if s == "": s = "MT326090.1" return jsonify([fetch_one_record(s)])