use actix_web::{
get,
web::{self, Data, Json, Path},
};
use crate::annotate::seqvars::csq::VcfVariant;
use super::{CustomError, versions::VersionsInfoResponse};
#[derive(
Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::IntoParams, utoipa::ToSchema,
)]
#[serde(rename_all = "snake_case")]
#[serde_with::skip_serializing_none]
pub(crate) struct FrequencyQuery {
pub assembly: String,
pub chromosome: String,
pub position: u32,
pub reference: String,
pub alternative: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
pub(crate) enum FrequencyResultEntry {
Autosomal(AutosomalResultEntry),
Gonosomal(GonosomalResultEntry),
Mitochondrial(MitochondrialResultEntry),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
pub(crate) struct AutosomalResultEntry {
pub gnomad_exomes_an: u32,
pub gnomad_exomes_hom: u32,
pub gnomad_exomes_het: u32,
pub gnomad_genomes_an: u32,
pub gnomad_genomes_hom: u32,
pub gnomad_genomes_het: u32,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
pub(crate) struct GonosomalResultEntry {
pub gnomad_exomes_an: u32,
pub gnomad_exomes_hom: u32,
pub gnomad_exomes_het: u32,
pub gnomad_exomes_hemi: u32,
pub gnomad_genomes_an: u32,
pub gnomad_genomes_hom: u32,
pub gnomad_genomes_het: u32,
pub gnomad_genomes_hemi: u32,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
pub(crate) struct MitochondrialResultEntry {
pub helix_an: u32,
pub helix_hom: u32,
pub helix_het: u32,
pub gnomad_genomes_an: u32,
pub gnomad_genomes_hom: u32,
pub gnomad_genomes_het: u32,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
pub(crate) struct FrequencyResponse {
pub version: VersionsInfoResponse,
pub query: FrequencyQuery,
pub result: Vec<FrequencyResultEntry>,
}
async fn handle_impl(
data: Data<super::WebServerData>,
_path: Path<()>,
query: web::Query<FrequencyQuery>,
) -> actix_web::Result<Json<FrequencyResponse>, super::CustomError> {
let FrequencyQuery {
assembly: genome_release,
chromosome,
position,
reference,
alternative,
} = query.clone().into_inner();
let annotator = data
.frequency_annotators
.get(&genome_release)
.ok_or_else(|| {
super::CustomError::new(anyhow::anyhow!(
"genome release not supported: {:?}",
&query.assembly
))
})?;
let mut result = Vec::new();
let g_var = VcfVariant {
chromosome,
position: position as i32,
reference,
alternative,
};
let frequencies = annotator
.annotate_variant(&g_var)
.map_err(|e| super::CustomError::new(anyhow::anyhow!("annotation failed: {}", &e)))?;
if let Some(frequencies) = frequencies {
result.push(frequencies);
}
let result = FrequencyResponse {
version: VersionsInfoResponse::from_web_server_data(data.into_inner().as_ref())
.map_err(|e| CustomError::new(anyhow::anyhow!("Problem determining version: {}", e)))?,
query: query.into_inner(),
result,
};
Ok(Json(result))
}
#[allow(clippy::unused_async)]
#[get("/seqvars/frequency")]
async fn handle(
data: Data<super::WebServerData>,
_path: Path<()>,
query: web::Query<FrequencyQuery>,
) -> actix_web::Result<Json<FrequencyResponse>, super::CustomError> {
handle_impl(data, _path, query).await
}
#[allow(clippy::unused_async)]
#[utoipa::path(
get,
operation_id = "seqvarsFrequency",
params(
FrequencyQuery
),
responses(
(status = 200, description = "Frequency information.", body = FrequencyResponse),
(status = 500, description = "Internal server error.", body = CustomError)
)
)]
#[get("/api/v1/seqvars/frequency")]
async fn handle_with_openapi(
data: Data<super::WebServerData>,
_path: Path<()>,
query: web::Query<FrequencyQuery>,
) -> actix_web::Result<Json<FrequencyResponse>, super::CustomError> {
handle_impl(data, _path, query).await
}