Skip to content

Commit

Permalink
added get samples, get subsamples
Browse files Browse the repository at this point in the history
  • Loading branch information
khoroshevskyi committed Feb 23, 2024
1 parent dc93470 commit ab42a07
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Fixed forking schema
- Improved forking efficiency [#129](https://github.com/pepkit/pepdbagent/issues/129)
- Added uploading project from dict
- Added get_config method to project module [#128](https://github.com/pepkit/pepdbagent/issues/128)
- Added get_config, get_smaples, get_subsamples methods to project module [#128](https://github.com/pepkit/pepdbagent/issues/128)
- Fixed error handling in views API [#130](https://github.com/pepkit/pepdbagent/issues/130)
- Added no_fail to views API

Expand Down
57 changes: 57 additions & 0 deletions pepdbagent/modules/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from sqlalchemy.exc import IntegrityError, NoResultFound
from sqlalchemy.orm import Session
from sqlalchemy import Select
import numpy as np

from peppy.const import (
SAMPLE_RAW_DICT_KEY,
Expand Down Expand Up @@ -256,6 +257,9 @@ def create(
elif isinstance(project, dict):
# verify if the dictionary has all necessary elements.
# samples should be always presented as list of dicts (orient="records"))
_LOGGER.warning(
f"Project f{namespace}/{name}:{tag} is provided as dictionary. Project won't be validated."
)
proj_dict = ProjectDict(**project).model_dump(by_alias=True)
else:
raise PEPDatabaseAgentError(
Expand Down Expand Up @@ -909,3 +913,56 @@ def get_config(self, namespace: str, name: str, tag: str) -> Union[dict, None]:
if result:
return result[0]
return None

def get_subsamples(self, namespace: str, name: str, tag: str) -> Union[list, None]:
"""
Get project subsamples by providing namespace, name, and tag
:param namespace: project namespace
:param name: project name
:param tag: project tag
:return: list with project subsamples
"""
statement = self._create_select_statement(name, namespace, tag)

with Session(self._sa_engine) as session:

found_prj = session.scalar(statement)

if found_prj:
_LOGGER.info(f"Project has been found: {found_prj.namespace}, {found_prj.name}")
subsample_dict = {}
if found_prj.subsamples_mapping:
for subsample in found_prj.subsamples_mapping:
if subsample.subsample_number not in subsample_dict.keys():
subsample_dict[subsample.subsample_number] = []
subsample_dict[subsample.subsample_number].append(subsample.subsample)
return list(subsample_dict.values())
else:
return []
else:
raise ProjectNotFoundError(
f"No project found for supplied input: '{namespace}/{name}:{tag}'. "
f"Did you supply a valid namespace and project?"
)

def get_samples(self, namespace: str, name: str, tag: str, raw: bool = True) -> list:
"""
Get project samples by providing namespace, name, and tag
:param namespace: project namespace
:param name: project name
:param tag: project tag
:param raw: if True, retrieve unprocessed (raw) PEP dict. [Default: True]
:return: list with project samples
"""
if raw:
return self.get(namespace=namespace, name=name, tag=tag, raw=True).get(
SAMPLE_RAW_DICT_KEY
)
return (
self.get(namespace=namespace, name=name, tag=tag, raw=False)
.sample_table.replace({np.nan: None})
.to_dict(orient="records")
)
1 change: 1 addition & 0 deletions requirements/requirements-all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ coloredlogs>=15.0.1
pytest-mock
pydantic>=2.0
psycopg>=3.1.15
numpy>=1.26.4
55 changes: 55 additions & 0 deletions tests/test_pepagent.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import peppy
import pytest
from sqlalchemy.exc import OperationalError
import numpy as np

import pepdbagent
from pepdbagent.exceptions import (
Expand Down Expand Up @@ -105,6 +106,60 @@ def test_get_config(self, initiate_pepdb_con, namespace, name):
ff.name = name
assert kk == ff.config

@pytest.mark.parametrize(
"namespace, name",
[
["namespace3", "subtables"],
],
)
def test_get_subsamples(self, initiate_pepdb_con, namespace, name):
prj_subtables = initiate_pepdb_con.project.get_subsamples(
namespace=namespace,
name=name,
tag="default",
)
orgiginal_prj = peppy.Project(get_path_to_example_file(namespace, name))

assert (
prj_subtables
== orgiginal_prj.to_dict(extended=True, orient="records")["_subsample_list"]
)

@pytest.mark.parametrize(
"namespace, name",
[
["namespace3", "subtables"],
],
)
def test_get_samples_raw(self, initiate_pepdb_con, namespace, name):
prj_samples = initiate_pepdb_con.project.get_samples(
namespace=namespace, name=name, tag="default", raw=True
)
orgiginal_prj = peppy.Project(get_path_to_example_file(namespace, name))

assert (
prj_samples == orgiginal_prj.to_dict(extended=True, orient="records")["_sample_dict"]
)

@pytest.mark.parametrize(
"namespace, name",
[
["namespace3", "subtables"],
],
)
def test_get_samples_processed(self, initiate_pepdb_con, namespace, name):
prj_samples = initiate_pepdb_con.project.get_samples(
namespace=namespace,
name=name,
tag="default",
raw=False,
)
orgiginal_prj = peppy.Project(get_path_to_example_file(namespace, name))

assert prj_samples == orgiginal_prj.sample_table.replace({np.nan: None}).to_dict(
orient="records"
)

@pytest.mark.parametrize(
"namespace, name,tag",
[
Expand Down

0 comments on commit ab42a07

Please sign in to comment.