-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Search basic #15
base: paralell_normalization
Are you sure you want to change the base?
Search basic #15
Changes from all commits
e3c407b
7453f10
0f41887
4e062bf
3b9c026
0a45a5e
d7b3cfd
dea2fe4
3b01289
afe2e0d
44d6dee
58aaa33
594cb47
e02e1f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,73 @@ | ||
from pydantic import BaseModel | ||
from pydantic import BaseModel, Field, validator | ||
from typing import List, Optional | ||
from enum import Enum | ||
|
||
__all__ = [ | ||
"ExperimentResult", | ||
"GeneExpression", | ||
"GeneExpressionData", | ||
"PaginationMeta", | ||
"GeneExpressionResponse", | ||
"MethodEnum", | ||
"QueryParameters", | ||
] | ||
|
||
|
||
class PaginatedRequest(BaseModel): | ||
page: int = Field(1, ge=1, description="Current page number") | ||
page_size: int = Field(100, ge=1, le=1000, description="Number of records per page") | ||
|
||
|
||
class PaginatedResponse(PaginatedRequest): | ||
total_records: int = Field(..., ge=0, description="Total number of records") | ||
total_pages: int = Field(..., ge=1, description="Total number of pages") | ||
|
||
|
||
class ExperimentResult(BaseModel): | ||
experiment_result_id: str | ||
assembly_id: str | None = None | ||
assembly_name: str | None = None | ||
experiment_result_id: str = Field(..., min_length=1, max_length=255) | ||
assembly_id: Optional[str] = Field(None, max_length=255) | ||
assembly_name: Optional[str] = Field(None, max_length=255) | ||
|
||
|
||
class GeneExpression(BaseModel): | ||
gene_code: str | ||
sample_id: str | ||
experiment_result_id: str | ||
gene_code: str = Field(..., min_length=1, max_length=255) | ||
sample_id: str = Field(..., min_length=1, max_length=255) | ||
experiment_result_id: str = Field(..., min_length=1, max_length=255) | ||
raw_count: int | ||
tpm_count: float | None = None | ||
tmm_count: float | None = None | ||
getmm_count: float | None = None | ||
tpm_count: Optional[float] = None | ||
tmm_count: Optional[float] = None | ||
getmm_count: Optional[float] = None | ||
|
||
|
||
class GeneExpressionData(BaseModel): | ||
gene_code: str = Field(..., min_length=1, max_length=255, description="Gene code") | ||
sample_id: str = Field(..., min_length=1, max_length=255, description="Sample ID") | ||
experiment_result_id: str = Field(..., min_length=1, max_length=255, description="Experiment result ID") | ||
count: float = Field(..., description="Expression count") | ||
method: str = Field(..., description="Method used to calculate the expression count") | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
class GeneExpressionResponse(PaginatedResponse): | ||
expressions: List[GeneExpressionData] | ||
|
||
|
||
class MethodEnum(str, Enum): | ||
raw = "raw" | ||
tpm = "tpm" | ||
tmm = "tmm" | ||
getmm = "getmm" | ||
|
||
|
||
class QueryParameters(PaginatedRequest): | ||
genes: Optional[List[str]] = Field(None, description="List of gene codes to retrieve") | ||
experiments: Optional[List[str]] = Field(None, description="List of experiment result IDs to retrieve data from") | ||
sample_ids: Optional[List[str]] = Field(None, description="List of sample IDs to retrieve data from") | ||
method: MethodEnum = Field(MethodEnum.raw, description="Data method to retrieve: 'raw', 'tpm', 'tmm', 'getmm'") | ||
|
||
@validator("genes", "experiments", "sample_ids", each_item=True) | ||
def validate_identifiers(cls, value): | ||
if not (1 <= len(value) <= 255): | ||
raise ValueError("Each identifier must be between 1 and 255 characters long.") | ||
if not value.replace("_", "").isalnum(): | ||
raise ValueError("Identifiers must contain only alphanumeric characters and underscores.") | ||
return value |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be in the expression router instead, with no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be in the expressions router, since it is has the |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
from fastapi import APIRouter, HTTPException, status, Query | ||
|
||
from transcriptomics_data_service.db import DatabaseDependency | ||
from transcriptomics_data_service.logger import LoggerDependency | ||
from transcriptomics_data_service.models import ( | ||
GeneExpressionData, | ||
GeneExpressionResponse, | ||
MethodEnum, | ||
QueryParameters, | ||
) | ||
|
||
query_router = APIRouter() | ||
|
||
|
||
async def get_expressions_handler( | ||
params: QueryParameters, | ||
db: DatabaseDependency, | ||
logger: LoggerDependency, | ||
): | ||
""" | ||
Handler for fetching and returning gene expression data. | ||
""" | ||
logger.info(f"Received query parameters: {params}") | ||
|
||
expressions, total_records = await db.fetch_gene_expressions( | ||
genes=params.genes, | ||
experiments=params.experiments, | ||
sample_ids=params.sample_ids, | ||
method=params.method.value, | ||
page=params.page, | ||
page_size=params.page_size, | ||
) | ||
|
||
if not expressions: | ||
raise HTTPException( | ||
status_code=status.HTTP_404_NOT_FOUND, | ||
detail="No gene expression data found for the given parameters.", | ||
) | ||
|
||
response_data = [] | ||
method_field = f"{params.method.value}_count" if params.method != MethodEnum.raw else "raw_count" | ||
for expr in expressions: | ||
count = getattr(expr, method_field) | ||
response_item = GeneExpressionData( | ||
gene_code=expr.gene_code, | ||
sample_id=expr.sample_id, | ||
experiment_result_id=expr.experiment_result_id, | ||
count=count, | ||
method=method_field, | ||
) | ||
response_data.append(response_item) | ||
|
||
total_pages = (total_records + params.page_size - 1) // params.page_size | ||
|
||
return GeneExpressionResponse( | ||
expressions=response_data, | ||
total_records=total_records, | ||
page=params.page, | ||
page_size=params.page_size, | ||
total_pages=total_pages, | ||
) | ||
|
||
|
||
@query_router.post( | ||
"/expressions", | ||
status_code=status.HTTP_200_OK, | ||
response_model=GeneExpressionResponse, | ||
) | ||
async def get_expressions_post( | ||
params: QueryParameters, | ||
db: DatabaseDependency, | ||
logger: LoggerDependency, | ||
): | ||
""" | ||
Retrieve gene expression data via POST request. | ||
|
||
Example JSON body: | ||
{ | ||
"genes": ["gene1", "gene2"], | ||
"experiments": ["exp1"], | ||
"sample_ids": ["sample1"], | ||
"method": "tmm", | ||
"page": 1, | ||
"page_size": 100 | ||
} | ||
""" | ||
return await get_expressions_handler(params, db, logger) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was there a specific reason to only include one count?