Skip to content

Commit 3131d5d

Browse files
authored
Merge pull request #231 from BioAnalyticResource/dev
Sync
2 parents 16ce80c + da8c9ee commit 3131d5d

47 files changed

Lines changed: 1312 additions & 493 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/bar-api.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ on:
1010
jobs:
1111
test:
1212

13-
runs-on: ubuntu-22.04
13+
runs-on: ubuntu-24.04
1414
strategy:
1515
matrix:
1616
python-version: [3.8, 3.9, 3.10.14, 3.11, 3.12]

api/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def create_app():
5353
# Now add routes
5454
from api.resources.gene_information import gene_information
5555
from api.resources.rnaseq_gene_expression import rnaseq_gene_expression
56+
from api.resources.microarray_gene_expression import microarray_gene_expression
5657
from api.resources.proxy import bar_proxy
5758
from api.resources.thalemine import thalemine
5859
from api.resources.snps import snps
@@ -65,6 +66,7 @@ def create_app():
6566

6667
bar_api.add_namespace(gene_information)
6768
bar_api.add_namespace(rnaseq_gene_expression)
69+
bar_api.add_namespace(microarray_gene_expression)
6870
bar_api.add_namespace(bar_proxy)
6971
bar_api.add_namespace(thalemine)
7072
bar_api.add_namespace(snps)

api/models/annotations_lookup.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,13 @@ class AgiAlias(db.Model):
1010
agi: db.Mapped[str] = db.mapped_column(db.String(30), primary_key=True, nullable=False)
1111
alias: db.Mapped[str] = db.mapped_column(db.String(30), primary_key=True, nullable=False)
1212
date: db.Mapped[datetime] = db.mapped_column(db.Date, primary_key=True, nullable=False)
13+
14+
15+
class AtAgiLookup(db.Model):
16+
__bind_key__ = "annotations_lookup"
17+
__tablename__ = "at_agi_lookup"
18+
__table_args__ = (db.Index("probeset_date_agi", "probeset", "agi", "date"),)
19+
20+
probeset: db.Mapped[str] = db.mapped_column(db.String(60), primary_key=True, nullable=False)
21+
agi: db.Mapped[str] = db.mapped_column(db.String(30), primary_key=True, nullable=False)
22+
date: db.Mapped[datetime] = db.mapped_column(db.Date, primary_key=True, nullable=False)

api/models/arabidopsis_ecotypes.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from api import db
2+
3+
4+
class SampleData(db.Model):
5+
__bind_key__ = "arabidopsis_ecotypes"
6+
__tablename__ = "sample_data"
7+
8+
sample_id: db.Mapped[int] = db.mapped_column(db.Integer, nullable=False)
9+
proj_id: db.Mapped[str] = db.mapped_column(db.String(15), nullable=False)
10+
sample_file_name: db.Mapped[str] = db.mapped_column(db.String)
11+
data_probeset_id: db.Mapped[str] = db.mapped_column(db.String(30), nullable=False, primary_key=True)
12+
data_signal: db.Mapped[float] = db.mapped_column(db.Float)
13+
data_call: db.Mapped[str] = db.mapped_column(db.String)
14+
data_p_val: db.Mapped[float] = db.mapped_column(db.Float)
15+
data_bot_id: db.Mapped[str] = db.mapped_column(db.String(16), nullable=False)

api/models/eplant2.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,15 @@ class GeneRIFs(db.Model):
3737
gene: db.Mapped[str] = db.mapped_column(db.String(11), nullable=False, primary_key=True)
3838
pubmed: db.Mapped[str] = db.mapped_column(db.String(11), nullable=False, primary_key=True)
3939
RIF: db.Mapped[str] = db.mapped_column(TEXT(), nullable=False, primary_key=True)
40+
41+
42+
class Publications(db.Model):
43+
__bind_key__ = "eplant2"
44+
__tablename__ = "publications"
45+
46+
gene: db.Mapped[str] = db.mapped_column(db.String(12), nullable=False, primary_key=True)
47+
author: db.Mapped[str] = db.mapped_column(db.String(64), nullable=False, primary_key=True)
48+
year: db.Mapped[str] = db.mapped_column(db.String(6), nullable=False, primary_key=True)
49+
journal: db.Mapped[str] = db.mapped_column(db.String(64), nullable=False, primary_key=True)
50+
title: db.Mapped[str] = db.mapped_column(TEXT(), nullable=False, primary_key=True)
51+
pubmed: db.Mapped[str] = db.mapped_column(db.String(16), nullable=False, primary_key=True)

api/resources/gene_information.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from markupsafe import escape
44
from api.models.annotations_lookup import AgiAlias
55
from api.models.eplant2 import Isoforms as EPlant2Isoforms
6+
from api.models.eplant2 import Publications as EPlant2Publications
67
from api.models.eplant_poplar import Isoforms as EPlantPoplarIsoforms
78
from api.models.eplant_tomato import Isoforms as EPlantTomatoIsoforms
89
from api.models.eplant_soybean import Isoforms as EPlantSoybeanIsoforms
@@ -86,6 +87,54 @@ def post(self):
8687
return BARUtils.error_exit("No data for the given species/genes"), 400
8788

8889

90+
@gene_information.route("/gene_publications/<string:species>/<string:gene_id>")
91+
class GenePublications(Resource):
92+
@gene_information.param("species", _in="path", default="arabidopsis")
93+
@gene_information.param("gene_id", _in="path", default="AT1G01010")
94+
def get(self, species="", gene_id=""):
95+
"""This end point provides publications given a gene ID."""
96+
publications = []
97+
98+
# Escape input
99+
species = escape(species)
100+
gene_id = escape(gene_id)
101+
102+
# truncate gene ID
103+
for i in range(len(gene_id)):
104+
if gene_id[i] == ".":
105+
gene_id = gene_id[0:i]
106+
break
107+
108+
# Set the database and check if genes are valid
109+
if species == "arabidopsis":
110+
database = EPlant2Publications
111+
112+
if not BARUtils.is_arabidopsis_gene_valid(gene_id):
113+
return BARUtils.error_exit("Invalid gene id"), 400
114+
else:
115+
return BARUtils.error_exit("No data for the given species")
116+
117+
# Get data
118+
rows = db.session.execute(db.select(database).where(database.gene == gene_id)).scalars().all()
119+
for row in rows:
120+
publications.append(
121+
{
122+
"gene_id": row.gene,
123+
"author": row.author,
124+
"year": row.year,
125+
"journal": row.journal,
126+
"title": row.title,
127+
"pubmed": row.pubmed,
128+
}
129+
)
130+
131+
# Return results if there are data
132+
if len(publications) > 0:
133+
return BARUtils.success_exit(publications)
134+
else:
135+
return BARUtils.error_exit("There are no data found for the given gene")
136+
137+
89138
@gene_information.route("/gene_isoforms/<string:species>/<string:gene_id>")
90139
class GeneIsoforms(Resource):
91140
@gene_information.param("species", _in="path", default="arabidopsis")
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from flask_restx import Namespace, Resource
2+
from markupsafe import escape
3+
from api import db
4+
from api.models.annotations_lookup import AtAgiLookup
5+
from api.models.arabidopsis_ecotypes import SampleData as EcotypesSampleData
6+
from api.utils.bar_utils import BARUtils
7+
from api.utils.world_efp_utils import WorldeFPUtils
8+
9+
10+
microarray_gene_expression = Namespace(
11+
"Microarray Gene Expression",
12+
description="Microarray (probe-based) Gene Expression data from the BAR Databases",
13+
path="/microarray_gene_expression",
14+
)
15+
16+
17+
@microarray_gene_expression.route("/world_efp/<string:species>/<string:gene_id>")
18+
class GetWorldeFPExpression(Resource):
19+
@microarray_gene_expression.param("species", _in="path", default="arabidopsis")
20+
@microarray_gene_expression.param("gene_id", _in="path", default="At1g01010")
21+
def get(self, species="", gene_id=""):
22+
"""This end point returns World Efp gene expression data"""
23+
species = escape(species)
24+
gene_id = escape(gene_id)
25+
26+
if species == "arabidopsis":
27+
if not BARUtils.is_arabidopsis_gene_valid(gene_id):
28+
return BARUtils.error_exit("Invalid gene id")
29+
else:
30+
return BARUtils.error_exit("Invalid species")
31+
subquery = (
32+
db.select(AtAgiLookup.probeset)
33+
.where(AtAgiLookup.agi == gene_id)
34+
.order_by(AtAgiLookup.date.desc())
35+
.limit(1)
36+
.subquery()
37+
)
38+
39+
sq_query = db.session.query(subquery)
40+
if sq_query.count() > 0:
41+
sq_result = sq_query[0][0]
42+
else:
43+
return BARUtils.error_exit("There are no data found for the given gene")
44+
45+
rows = db.session.execute(
46+
db.select(
47+
EcotypesSampleData.data_probeset_id, EcotypesSampleData.data_signal, EcotypesSampleData.data_bot_id
48+
).where(EcotypesSampleData.data_probeset_id == sq_result)
49+
).all()
50+
final_json = {}
51+
52+
if len(rows) > 0:
53+
for row in rows:
54+
if row[2][5:8] not in final_json:
55+
final_json[row[2][5:8]] = WorldeFPUtils.wrap_json(row[2][5:8], row[2], row[1], row[0])
56+
elif row[2][5:8] in final_json:
57+
final_json[row[2][5:8]]["values"].update({row[2]: row[1]})
58+
return BARUtils.success_exit(final_json)
59+
else:
60+
return BARUtils.error_exit("There are no data found for the given gene")

0 commit comments

Comments
 (0)