use actix_web::{
Responder, get,
web::{self, Data, Json, Path},
};
use crate::{
annotate::strucvars::csq::{
StrucvarsGeneTranscriptEffects,
interface::{self, StrucvarsSvType},
},
server::run::actix_server::CustomError,
};
use super::versions::VersionsInfoResponse;
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[serde_with::skip_serializing_none]
struct Query {
pub assembly: String,
pub chromosome: String,
pub start: i32,
pub stop: Option<i32>,
pub sv_type: String,
}
impl interface::StrucVar for Query {
fn chrom(&self) -> String {
self.chromosome.clone()
}
fn chrom2(&self) -> String {
self.chromosome.clone()
}
fn start(&self) -> i32 {
self.start
}
fn stop(&self) -> i32 {
if self.sv_type() == interface::StrucvarsSvType::Ins {
self.start
} else {
self.stop.unwrap_or(self.start)
}
}
fn sv_type(&self) -> interface::StrucvarsSvType {
match self.sv_type.to_uppercase().as_ref() {
"DEL" => interface::StrucvarsSvType::Del,
"DUP" => interface::StrucvarsSvType::Dup,
"INS" => interface::StrucvarsSvType::Ins,
"BND" => interface::StrucvarsSvType::Bnd,
"INV" => interface::StrucvarsSvType::Inv,
"CNV" => interface::StrucvarsSvType::Cnv,
_ => panic!("unexpected SVTYPE: {}", self.sv_type),
}
}
fn strand_orientation(&self) -> interface::StrandOrientation {
interface::StrandOrientation::NotApplicable
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Container {
pub version: crate::common::Version,
pub query: Query,
pub result: Vec<StrucvarsGeneTranscriptEffects>,
}
#[allow(clippy::unused_async)]
#[get("/strucvars/csq")]
async fn handle(
data: Data<super::WebServerData>,
_path: Path<()>,
query: web::Query<Query>,
) -> actix_web::Result<impl Responder, super::CustomError> {
let predictor = data
.strucvars_predictors
.get(&query.assembly)
.ok_or_else(|| {
super::CustomError::new(anyhow::anyhow!(
"genome release not supported: {:?}",
&query.assembly
))
})?;
let result = predictor.compute_tx_effects(&query.clone().into_inner());
let result = Container {
version: crate::common::Version::new(predictor.data_version()),
query: query.into_inner(),
result,
};
Ok(Json(result))
}
#[derive(
Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::IntoParams, utoipa::ToSchema,
)]
#[serde(rename_all = "snake_case")]
#[serde_with::skip_serializing_none]
pub(crate) struct StrucvarsCsqQuery {
pub assembly: String,
pub chromosome: String,
pub start: i32,
pub stop: Option<i32>,
pub sv_type: StrucvarsSvType,
}
impl interface::StrucVar for StrucvarsCsqQuery {
fn chrom(&self) -> String {
self.chromosome.clone()
}
fn chrom2(&self) -> String {
self.chromosome.clone()
}
fn start(&self) -> i32 {
self.start
}
fn stop(&self) -> i32 {
if self.sv_type() == interface::StrucvarsSvType::Ins {
self.start
} else {
self.stop.unwrap_or(self.start)
}
}
fn sv_type(&self) -> interface::StrucvarsSvType {
self.sv_type
}
fn strand_orientation(&self) -> interface::StrandOrientation {
interface::StrandOrientation::NotApplicable
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
pub(crate) struct StrucvarsCsqResponse {
pub version: VersionsInfoResponse,
pub query: StrucvarsCsqQuery,
pub result: Vec<StrucvarsGeneTranscriptEffects>,
}
#[allow(clippy::unused_async)]
#[utoipa::path(
get,
operation_id = "strucvarsCsq",
params(
StrucvarsCsqQuery
),
responses(
(status = 200, description = "Strucvars consequence information.", body = StrucvarsCsqResponse),
(status = 500, description = "Internal server error.", body = CustomError)
)
)]
#[get("/api/v1/strucvars/csq")]
async fn handle_with_openapi(
data: Data<super::WebServerData>,
_path: Path<()>,
query: web::Query<StrucvarsCsqQuery>,
) -> actix_web::Result<Json<StrucvarsCsqResponse>, CustomError> {
let predictor = data
.strucvars_predictors
.get(&query.assembly)
.ok_or_else(|| {
super::CustomError::new(anyhow::anyhow!(
"genome release not supported: {:?}",
&query.assembly
))
})?;
let result = predictor.compute_tx_effects(&query.clone().into_inner());
let result = StrucvarsCsqResponse {
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))
}