use std::collections::HashMap;
use serde::Deserialize;
use crate::{ReqError, make_agent};
const BASE_URL: &str = "https://www.ebi.ac.uk/pdbe-srv/pdbechem/chemicalCompound/show";
const MAPPINGS_URL: &str = "https://www.ebi.ac.uk/pdbe/api/mappings";
#[derive(Clone, Debug, Deserialize)]
pub struct SiftsResiduePosition {
pub residue_number: i32,
pub author_residue_number: Option<i32>,
#[serde(default)]
pub author_insertion_code: Option<String>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct SiftsMapping {
pub entity_id: u32,
pub chain_id: String,
pub struct_asym_id: String,
pub unp_start: u32,
pub unp_end: u32,
pub start: SiftsResiduePosition,
pub end: SiftsResiduePosition,
pub identity: f32,
pub coverage: f32,
}
#[derive(Clone, Debug)]
pub struct SiftsUniprotMapping {
pub accession: String,
pub identifier: String,
pub mappings: Vec<SiftsMapping>,
}
#[derive(Deserialize)]
struct RawUniprotEntry {
identifier: String,
mappings: Vec<SiftsMapping>,
}
#[derive(Deserialize)]
struct RawUniprotSection {
#[serde(rename = "UniProt")]
uniprot: HashMap<String, RawUniprotEntry>,
}
pub fn load_uniprot_mappings(pdb_id: &str) -> Result<Vec<SiftsUniprotMapping>, ReqError> {
let url = format!("{MAPPINGS_URL}/uniprot/{}", pdb_id.to_lowercase());
let agent = make_agent();
let resp = agent.get(&url).call()?.body_mut().read_to_string()?;
let mut raw: HashMap<String, RawUniprotSection> = serde_json::from_str(&resp)?;
let section = raw.drain().next().ok_or(ReqError::Deserialize)?.1;
Ok(section
.uniprot
.into_iter()
.map(|(accession, entry)| SiftsUniprotMapping {
accession,
identifier: entry.identifier,
mappings: entry.mappings,
})
.collect())
}
pub fn open_overview(id: &str) {
if let Err(e) = webbrowser::open(&format!("{BASE_URL}/{id}")) {
eprintln!("Failed to open the web browser: {:?}", e);
}
}
fn sdf_url(ident: &str) -> String {
format!(
"https://www.ebi.ac.uk/pdbe/static/files/pdbechem_v2/{}_ideal.sdf",
ident.to_uppercase()
)
}
pub fn load_sdf(ident: &str) -> Result<String, ReqError> {
let agent = make_agent();
Ok(agent
.get(sdf_url(ident))
.call()?
.body_mut()
.read_to_string()?)
}