From d9ea31814ef028ea64e1ade9f4dbf73082c041c0 Mon Sep 17 00:00:00 2001 From: asherpasha Date: Wed, 29 Oct 2025 14:54:52 -0400 Subject: [PATCH] GAIA: initial commit --- api/__init__.py | 2 ++ api/models/gaia.py | 10 ++++++++++ api/resources/gaia.py | 40 ++++++++++++++++++++++++++++++++++++++++ api/utils/bar_utils.py | 11 +++++++++++ 4 files changed, 63 insertions(+) create mode 100644 api/models/gaia.py create mode 100644 api/resources/gaia.py diff --git a/api/__init__.py b/api/__init__.py index 43164b5..9ba5405 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -52,6 +52,7 @@ def create_app(): # Now add routes from api.resources.gene_information import gene_information + from api.resources.gaia import gaia from api.resources.rnaseq_gene_expression import rnaseq_gene_expression from api.resources.microarray_gene_expression import microarray_gene_expression from api.resources.proxy import bar_proxy @@ -66,6 +67,7 @@ def create_app(): from api.resources.llama3 import llama3 bar_api.add_namespace(gene_information) + bar_api.add_namespace(gaia) bar_api.add_namespace(rnaseq_gene_expression) bar_api.add_namespace(microarray_gene_expression) bar_api.add_namespace(bar_proxy) diff --git a/api/models/gaia.py b/api/models/gaia.py new file mode 100644 index 0000000..7745a87 --- /dev/null +++ b/api/models/gaia.py @@ -0,0 +1,10 @@ +from api import db +from sqlalchemy.dialects.mysql import json + + +class Aliases(db.Model): + __bind_key__ = "gaia" + __tablename__ = "aliases" + + id: db.Mapped[int] = db.mapped_column(db.Integer, nullable=False, primary_key=True) + data: db.Mapped[json] = db.mapped_column(db.JSON, nullable=True, primary_key=False) diff --git a/api/resources/gaia.py b/api/resources/gaia.py new file mode 100644 index 0000000..611ae9c --- /dev/null +++ b/api/resources/gaia.py @@ -0,0 +1,40 @@ +from flask_restx import Namespace, Resource +from markupsafe import escape +from api import db +from api.utils.bar_utils import BARUtils +from api.models.gaia import Aliases +from sqlalchemy import func +import json + +gaia = Namespace("Gaia", description="Gaia", path="/gaia") + + +@gaia.route("/aliases/") +class GaiaAliases(Resource): + @gaia.param("identifier", _in="path", default="ABI3") + def get(self, identifier=""): + + # Escape input + identifier = escape(identifier) + + # Is it valid + if BARUtils.is_alphanumeric(identifier): + # Convert to json + identifier_json = json.dumps([identifier]) + + # Get data + # Note: SQLAlchmemy or_ did not work here. Query had AND for some reason. + query = db.select(Aliases).filter( + (func.json_contains(func.lower(Aliases.data), func.lower(identifier_json), "$.aliases")) + | (func.json_extract(func.lower(Aliases.data), "$.geneid") == func.lower(identifier)) + | (func.json_extract(func.lower(Aliases.data), "$.locus") == func.lower(identifier)), + ) + row = db.session.execute(query).scalars().first() + + if row: + return BARUtils.success_exit(row.data) + else: + return BARUtils.error_exit("Nothing found"), 404 + + else: + return BARUtils.error_exit("Invalid identifier"), 400 diff --git a/api/utils/bar_utils.py b/api/utils/bar_utils.py index 12e5b7c..0153a58 100644 --- a/api/utils/bar_utils.py +++ b/api/utils/bar_utils.py @@ -252,6 +252,17 @@ def is_integer(data): else: return False + @staticmethod + def is_alphanumeric(data): + """Check if the input is alphanumeric. + :param data + :return: True if alphanumeric + """ + if re.search(r"^[a-z0-9]{1,50}$", data, re.I): + return True + else: + return False + @staticmethod def format_poplar(poplar_gene): """Format Poplar gene ID to be Potri.016G107900, i.e. capitalized P and G