From 415eb89651081494cc80337f7f41a6f6ad6c40e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20S=C3=A1nchez-Gallego?= Date: Wed, 7 Aug 2024 15:44:29 -0700 Subject: [PATCH] Implement /target/parents endpoint --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- python/valis/db/models.py | 12 +++++++++++- python/valis/db/queries.py | 27 +++++++++++++++++++++++++++ python/valis/routes/target.py | 25 +++++++++++++++++++++++-- 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 981a2f1..8e54bab 100644 --- a/poetry.lock +++ b/poetry.lock @@ -5754,13 +5754,13 @@ docs = ["Sphinx (>=7.2.0)", "importlib-metadata (>=1.6.0)", "jinja2 (<3.1)", "re [[package]] name = "sdssdb" -version = "0.12.3" +version = "0.12.4" description = "SDSS product for database management" optional = false python-versions = ">=3.6" files = [ - {file = "sdssdb-0.12.3-py3-none-any.whl", hash = "sha256:67102b0075cbe79a399a791d3e7e018440429d5a7c3d4734b9bdc002a0e70998"}, - {file = "sdssdb-0.12.3.tar.gz", hash = "sha256:743e9fdf81da22b700323417f235eb3d0145e4336e65c78b96cb0f9e6168c1b7"}, + {file = "sdssdb-0.12.4-py3-none-any.whl", hash = "sha256:cba5393621d6a7a455954c8a0ca695f91846e109043435669545b01804b6bd11"}, + {file = "sdssdb-0.12.4.tar.gz", hash = "sha256:ac4c1e021cc3454c1fed319cf6e646041af7378d322b0bb89f852366e6471e1a"}, ] [package.dependencies] @@ -7528,4 +7528,4 @@ solara = ["sdss-solara"] [metadata] lock-version = "2.0" python-versions = "~3.10" -content-hash = "5a6c6add56086dab357ab8112c067e2c46e1a000c0b96a075e738ea24e932159" +content-hash = "392b8427145afc9c48e6c3ee2bf315d3699aaf00d7ab207d1d3f19bf938b1ba9" diff --git a/pyproject.toml b/pyproject.toml index c0f5eb4..6db3a8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ httpx = "^0.24.0" astroquery = "^0.4.6" pandas = "^1.5.3" SQLAlchemy = "^1.4.35" -sdssdb = "^0.12.3" +sdssdb = "^0.12.4" deepmerge = "^1.1.1" fuzzy-types = "^0.1.3" sdss-solara = {git = "https://github.com/sdss/sdss_solara.git", rev = "main", optional = true} diff --git a/python/valis/db/models.py b/python/valis/db/models.py index d5ff842..cfdec05 100644 --- a/python/valis/db/models.py +++ b/python/valis/db/models.py @@ -192,6 +192,16 @@ class CatalogModel(PeeweeBase): parallax: Optional[float] = None +class ParentCatalogModel(PeeweeBase): + """Pydantic model for parent catalog information """ + + sdss_id: int + catalogid: int + catalog: str + field_name: str + parent_catalog_id: int | str + + class CatalogResponse(CatalogModel, SDSSidFlatBase): """ Response model for source catalog and sdss_id information """ pass @@ -243,4 +253,4 @@ class MapperName(str, Enum): """Mapper names""" MWM: str = 'MWM' BHM: str = 'BHM' - LVM: str = 'LVM' \ No newline at end of file + LVM: str = 'LVM' diff --git a/python/valis/db/queries.py b/python/valis/db/queries.py index ac0c526..611f53a 100644 --- a/python/valis/db/queries.py +++ b/python/valis/db/queries.py @@ -694,6 +694,33 @@ def get_catalog_sources(sdss_id: int) -> peewee.ModelSelect: join(s, on=(s.c.catalogid == cat.Catalog.catalogid)).order_by(cat.Catalog.version.desc()) +def get_parent_catalog_data(sdss_id: int, catalog: str) -> peewee.ModelSelect: + """Returns parent catalog data for a given target.""" + + SID = cat.SDSS_ID_To_Catalog + + cat_field: peewee.Field | None = None + cat_pk_name: str | None = None + for field in SID._meta.fields.values(): + if '__' not in field.name: + continue + if field.name.split('__')[0] == catalog: + cat_field = field + cat_pk_name = field.name.split('__')[1] + break + + if cat_field is None or cat_pk_name is None: + raise ValueError(f'Catalog {catalog} not found in SDSS_ID_To_Catalog table.') + + return (SID.select(SID.sdss_id, + SID.catalogid, + peewee.Value(catalog).alias('catalog'), + peewee.Value(cat_pk_name).alias('field_name'), + field.alias('parent_catalog_id')) + .where(SID.sdss_id == sdss_id) + .order_by(SID.catalogid)) + + def get_target_cartons(sdss_id: int) -> peewee.ModelSelect: """ Get the carton info for a target sdss_id diff --git a/python/valis/routes/target.py b/python/valis/routes/target.py index c56e491..3ea945f 100644 --- a/python/valis/routes/target.py +++ b/python/valis/routes/target.py @@ -14,9 +14,10 @@ from valis.routes.base import Base from valis.db.queries import (get_target_meta, get_a_spectrum, get_catalog_sources, - get_target_cartons, get_target_pipeline) + get_parent_catalog_data, get_target_cartons, + get_target_pipeline) from valis.db.db import get_pw_db -from valis.db.models import CatalogResponse, CartonModel, PipesModel, SDSSModel +from valis.db.models import CatalogResponse, CartonModel, ParentCatalogModel, PipesModel, SDSSModel router = APIRouter() @@ -183,6 +184,26 @@ async def get_catalogs(self, sdss_id: int = Path(title="The sdss_id of the targe """ Return catalog information for a given sdss_id """ return get_catalog_sources(sdss_id).dicts().iterator() + @router.get('/parents/{parent_catalog}/{sdss_id}', + dependencies=[Depends(get_pw_db)], + response_model=ParentCatalogModel, + summary='Retrieve parent catalog information for a taget by sdss_id') + async def get_parents(self, + parent_catalog: str = Path(title='The parent catalog to search', + example='gaia_dr3_source'), + sdss_id = Path(title='The sdss_id of the target to get', + example=129055990)): + """Return parent catalog information for a given sdss_id """ + + try: + result = get_parent_catalog_data(sdss_id, parent_catalog).dicts() + if len(result) == 0: + raise ValueError(f'No parent catalog data found for sdss_id {sdss_id}') + except Exception as e: + raise HTTPException(status_code=500, detail=f'Error: {e}') + + return result[0] + @router.get('/cartons/{sdss_id}', summary='Retrieve carton information for a target sdss_id', dependencies=[Depends(get_pw_db)], response_model=List[CartonModel],