use std::io::Write;
use anyhow::Result;
use bon::{Builder, builder};
use clap::{Parser, Subcommand};
use ggetrs_string::{OutputFormat, StringNetworkType, match_output};
use serde_json::{Value, json};
#[derive(Subcommand)]
pub enum ModString {
MapIds {
#[clap(flatten)]
args: StringMappingArgs,
#[clap(flatten)]
output: OutputArgs,
},
Network {
#[clap(flatten)]
args: StringNetworkArgs,
#[clap(flatten)]
output: OutputArgs,
},
Homology {
#[clap(flatten)]
args: StringHomologyArgs,
#[clap(flatten)]
output: OutputArgs,
},
Interactions {
#[clap(flatten)]
args: StringInteractionsArgs,
#[clap(flatten)]
output: OutputArgs,
},
Enrichment {
#[clap(flatten)]
args: StringFunctionalEnrichmentArgs,
#[clap(flatten)]
output: OutputArgs,
},
Annotations {
#[clap(flatten)]
args: StringFunctionalAnnotationArgs,
#[clap(flatten)]
output: OutputArgs,
},
PpiEnrichment {
#[clap(flatten)]
args: StringPpiEnrichmentArgs,
#[clap(flatten)]
output: OutputArgs,
},
}
#[derive(Debug, Clone, Parser)]
#[clap(next_help_heading = "Output Arguments")]
pub struct OutputArgs {
#[clap(short, long)]
pub output: Option<String>,
#[clap(short, long, default_value = "tsv")]
pub format: OutputFormat,
}
impl OutputArgs {
pub fn get_writer(&self) -> Result<Box<dyn Write>> {
match_output(self.output.clone())
}
}
#[derive(Debug, Clone, Parser, Builder)]
#[clap(next_help_heading = "STRING Network Arguments")]
pub struct StringNetworkArgs {
#[clap(required = true)]
pub identifiers: Vec<String>,
#[clap(short, long, default_value = "9606")]
#[builder(default = 9606)]
pub species: usize,
#[clap(short, long)]
pub required_score: Option<f64>,
#[clap(short, long, default_value = "functional")]
#[builder(default = StringNetworkType::Functional)]
pub network_type: StringNetworkType,
#[clap(short, long)]
pub add_nodes: Option<usize>,
#[clap(short = 'q', long)]
#[builder(default = false)]
pub show_query_node_labels: bool,
#[clap(short, long, default_value = "ggetrs")]
#[builder(default = "ggetrs".to_string())]
pub caller_identity: String,
}
impl StringNetworkArgs {
#[must_use]
pub fn build_post(&self) -> Value {
let mut data = json!({
"identifiers": self.identifiers.join("%0d"),
"species": self.species,
"network_type": self.network_type.to_string(),
"caller_identity": self.caller_identity,
});
data["show_query_node_labels"] = if self.show_query_node_labels {
json!(1)
} else {
json!(0)
};
if let Some(score) = self.required_score {
data["required_score"] = json!(score);
}
if let Some(nodes) = self.add_nodes {
data["add_nodes"] = json!(nodes);
}
data
}
}
#[derive(Debug, Clone, Parser, Builder)]
#[clap(next_help_heading = "STRING Homology Arguments")]
pub struct StringHomologyArgs {
#[clap(required = true)]
pub identifiers: Vec<String>,
#[clap(short, long, default_value = "9606")]
#[builder(default = 9606)]
pub species: usize,
#[clap(short, long, default_value = "ggetrs")]
#[builder(default = "ggetrs".to_string())]
pub caller_identity: String,
}
impl StringHomologyArgs {
#[must_use]
pub fn build_post(&self) -> Value {
json!({
"identifiers": self.identifiers.join("%0d"),
"species": self.species,
"caller_identity": self.caller_identity,
})
}
}
#[derive(Debug, Clone, Parser, Builder)]
#[clap(next_help_heading = "STRING Mapping Identifiers Arguments")]
pub struct StringMappingArgs {
#[clap(required = true)]
pub identifiers: Vec<String>,
#[clap(short, long)]
#[builder(default = false)]
pub echo_query: bool,
#[clap(short, long)]
pub limit: Option<usize>,
#[clap(short, long, default_value = "9606")]
#[builder(default = 9606)]
pub species: usize,
#[clap(short, long, default_value = "ggetrs")]
#[builder(default = "ggetrs".to_string())]
pub caller_identity: String,
}
impl StringMappingArgs {
#[must_use]
pub fn build_post(&self) -> Value {
let mut data = json!({
"identifiers": self.identifiers.join("%0d"),
"echo_query": self.echo_query,
"species": self.species,
"caller_identity": self.caller_identity,
});
if let Some(limit) = self.limit {
data["limit"] = json!(limit);
}
data
}
}
#[derive(Debug, Clone, Parser, Builder)]
#[clap(next_help_heading = "STRING Interactions Arguments")]
pub struct StringInteractionsArgs {
#[clap(required = true)]
pub identifiers: Vec<String>,
#[clap(short, long, default_value = "9606")]
#[builder(default = 9606)]
pub species: usize,
#[clap(short, long)]
pub limit: Option<usize>,
#[clap(short, long)]
pub required_score: Option<f64>,
#[clap(short, long, default_value = "functional")]
#[builder(default = StringNetworkType::Functional)]
pub network_type: StringNetworkType,
#[clap(short, long, default_value = "ggetrs")]
#[builder(default = "ggetrs".to_string())]
pub caller_identity: String,
}
impl StringInteractionsArgs {
#[must_use]
pub fn build_post(&self) -> Value {
let mut data = json!({
"identifiers": self.identifiers.join("%0d"),
"species": self.species,
"network_type": self.network_type.to_string(),
"caller_identity": self.caller_identity,
});
if let Some(limit) = self.limit {
data["limit"] = json!(limit);
}
if let Some(score) = self.required_score {
data["required_score"] = json!(score);
}
data
}
}
#[derive(Debug, Clone, Parser, Builder)]
#[clap(next_help_heading = "STRING Functional Enrichment Arguments")]
pub struct StringFunctionalEnrichmentArgs {
#[clap(required = true)]
pub identifiers: Vec<String>,
#[clap(short, long)]
pub background: Option<Vec<String>>,
#[clap(short, long, default_value = "9606")]
#[builder(default = 9606)]
pub species: usize,
#[clap(short, long, default_value = "ggetrs")]
#[builder(default = "ggetrs".to_string())]
pub caller_identity: String,
}
impl StringFunctionalEnrichmentArgs {
#[must_use]
pub fn build_post(&self) -> Value {
let mut data = json!({
"identifiers": self.identifiers.join("%0d"),
"species": self.species,
"caller_identity": self.caller_identity,
});
if let Some(background) = &self.background {
data["background"] = json!(background.join("%0d"));
}
data
}
}
#[derive(Debug, Clone, Parser, Builder)]
#[clap(next_help_heading = "STRING Functional Annotations Arguments")]
pub struct StringFunctionalAnnotationArgs {
#[clap(required = true)]
pub identifiers: Vec<String>,
#[clap(short, long, default_value = "9606")]
#[builder(default = 9606)]
pub species: usize,
#[clap(short = 'p', long)]
#[builder(default = false)]
pub allow_pubmed: bool,
#[clap(short = 'P', long)]
#[builder(default = false)]
pub only_pubmed: bool,
#[clap(short, long, default_value = "ggetrs")]
#[builder(default = "ggetrs".to_string())]
pub caller_identity: String,
}
impl StringFunctionalAnnotationArgs {
#[must_use]
pub fn build_post(&self) -> Value {
json!({
"identifiers": self.identifiers.join("%0d"),
"species": self.species,
"caller_identity": self.caller_identity,
"allow_pubmed": self.allow_pubmed,
"only_pubmed": self.only_pubmed,
})
}
}
#[derive(Debug, Clone, Parser, Builder)]
#[clap(next_help_heading = "STRING PPI Enrichment Arguments")]
pub struct StringPpiEnrichmentArgs {
#[clap(required = true)]
pub identifiers: Vec<String>,
#[clap(short, long, default_value = "9606")]
#[builder(default = 9606)]
pub species: usize,
#[clap(short, long)]
pub required_score: Option<f64>,
#[clap(short, long)]
pub background: Option<Vec<String>>,
#[clap(short, long, default_value = "ggetrs")]
#[builder(default = "ggetrs".to_string())]
pub caller_identity: String,
}
impl StringPpiEnrichmentArgs {
#[must_use]
pub fn build_post(&self) -> Value {
let mut data = json!({
"identifiers": self.identifiers.join("%0d"),
"species": self.species,
"caller_identity": self.caller_identity,
});
if let Some(score) = self.required_score {
data["required_score"] = json!(score);
}
if let Some(background) = &self.background {
data["background"] = json!(background.join("%0d"));
}
data
}
}