Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/formats/ncbi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,9 @@
Ok(gt)
}

pub fn save<'t, T: 't, P: AsRef<Path>, X: Taxonomy<'t, T>>(
tax: &'t X,
out_dir: P,
) -> TaxonomyResult<()>
pub fn save<'t, T, P: AsRef<Path>, X: Taxonomy<'t, T>>(tax: &'t X, out_dir: P) -> TaxonomyResult<()>
where
T: Clone + Debug + Display + PartialEq,
T: 't + Clone + Debug + Display + PartialEq,
{
let dir = out_dir.as_ref();
std::fs::create_dir_all(dir)?;
Expand All @@ -107,7 +104,7 @@
.unwrap_or_default()
};
name_writer
.write_all(format!("{}\t|\t{}\t|\t\t|\tscientific name\t|\n", &key, name).as_bytes())?;

Check warning on line 107 in src/formats/ncbi.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant reference in `format!` argument
node_writer.write_all(
format!(
"{}\t|\t{}\t|\t{}\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n",
Expand All @@ -134,7 +131,7 @@
let nodes =
"1\t|\t1\t|\tno rank\t|\t\t|\t8\t|\t0\t|\t1\t|\t0\t|\t0\t|\t0\t|\t0\t|\t0\t|\t\t|
10239\t|\t1\t|\tno_rank\t|\t\t|\t9\t|\t0\t|\t1\t|\t0\t|\t0\t|\t0\t|\t0\t|\t0\t|\t\t|
2\t|\t131567\t|\tsuperkingdom\t|\t\t|\t0\t|\t0\t|\t11\t|\t0\t|\t0\t|\t0\t|\t0\t|\t0\t|\t\t|
2\t|\t131567\t|\tdomain\t|\t\t|\t0\t|\t0\t|\t11\t|\t0\t|\t0\t|\t0\t|\t0\t|\t0\t|\t\t|
543\t|\t91347\t|\tfamily\t|\t\t|\t0\t|\t1\t|\t11\t|\t1\t|\t0\t|\t1\t|\t0\t|\t0\t|\t\t|
561\t|\t543\t|\tgenus\t|\t\t|\t0\t|\t1\t|\t11\t|\t1\t|\t0\t|\t1\t|\t0\t|\t0\t|\t\t|
562\t|\t561\t|\tspecies\t|\tEC\t|\t0\t|\t1\t|\t11\t|\t1\t|\t0\t|\t1\t|\t1\t|\t0\t|\t\t|
Expand Down Expand Up @@ -239,6 +236,9 @@
Some(("561", 1.))
);

// Check Bacteria (2) keeps its "domain" rank through save/load
assert_eq!(Taxonomy::<&str>::rank(&tax2, "2").unwrap(), TaxRank::Domain);

// Check Escherichia (561)
assert_eq!(Taxonomy::<&str>::name(&tax2, "561").unwrap(), "Escherichia");
assert_eq!(
Expand Down
194 changes: 78 additions & 116 deletions src/rank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,61 +111,115 @@ pub enum TaxRank {
}

impl TaxRank {
/// Converts a TaxRank into a one of the rank strings NCBI uses.
/// Note that this doesn't handle ranks that are not used by the NCBI taxonomy.
/// Converts a TaxRank into the rank string NCBI uses (or, for ranks NCBI
/// doesn't define, our own lowercase spelling). Never coerces to "no rank".
pub fn to_ncbi_rank(self) -> &'static str {
self.as_str()
}

pub fn as_str(self) -> &'static str {
match self {
TaxRank::Superkingdom => "superkingdom",
TaxRank::Domain => "domain",
TaxRank::AcellularRoot => "acellular root",
TaxRank::CellularRoot => "cellular root",
TaxRank::Subdomain => "subdomain",
TaxRank::Realm => "realm",
TaxRank::Subrealm => "subrealm",
TaxRank::Hyperkingdom => "hyperkingdom",
TaxRank::Superkingdom => "superkingdom",
TaxRank::Kingdom => "kingdom",
TaxRank::Subkingdom => "subkingdom",
TaxRank::Infrakingdom => "infrakingdom",
TaxRank::Parvkingdom => "parvkingdom",
TaxRank::Superphylum => "superphylum",
TaxRank::Phylum => "phylum",
TaxRank::Subphylum => "subphylum",
TaxRank::Infraphylum => "infraphylum",
TaxRank::Microphylum => "microphylum",
TaxRank::Superclass => "superclass",
TaxRank::Class => "class",
TaxRank::Subclass => "subclass",
TaxRank::Infraclass => "infraclass",
TaxRank::Parvclass => "parvclass",
TaxRank::Superdivision => "superdivision",
TaxRank::Division => "division",
TaxRank::Subdivision => "subdivision",
TaxRank::Infradivision => "infradivision",
TaxRank::Superlegion => "superlegion",
TaxRank::Legion => "legion",
TaxRank::Sublegion => "sublegion",
TaxRank::Infralegion => "infralegion",
TaxRank::Supercohort => "supercohort",
TaxRank::Cohort => "cohort",
TaxRank::Subcohort => "subcohort",
TaxRank::Infracohort => "infracohort",
TaxRank::Superorder => "superorder",
TaxRank::Gigaorder => "gigaorder",
TaxRank::Magnorder => "magnorder",
TaxRank::Grandorder => "grandorder",
TaxRank::Mirorder => "mirorder",
TaxRank::SeriesFish => "series fish",
TaxRank::Order => "order",
TaxRank::Nanorder => "nanorder",
TaxRank::Hypoorder => "hypoorder",
TaxRank::Minorder => "minorder",
TaxRank::Suborder => "suborder",
TaxRank::Infraorder => "infraorder",
TaxRank::Parvorder => "parvorder",
TaxRank::Section => "section",
TaxRank::Subsection => "subsection",
TaxRank::Gigafamily => "gigafamily",
TaxRank::Megafamily => "megafamily",
TaxRank::Grandfamily => "grandfamily",
TaxRank::Hyperfamily => "hyperfamily",
TaxRank::Superfamily => "superfamily",
TaxRank::Epifamily => "epifamily",
TaxRank::SeriesLepidoptera => "series lepidoptera",
TaxRank::GroupLepidoptera => "group lepidoptera",
TaxRank::Family => "family",
TaxRank::Subfamily => "subfamily",
TaxRank::Infrafamily => "infrafamily",
TaxRank::Supertribe => "supertribe",
TaxRank::Tribe => "tribe",
TaxRank::Subtribe => "subtribe",
TaxRank::Infratribe => "infratribe",
TaxRank::Genus => "genus",
TaxRank::Series => "series",
TaxRank::Subgenus => "subgenus",
TaxRank::Series => "series",
TaxRank::SubseriesBotany => "subseries botany",
TaxRank::SpeciesGroup => "species group",
TaxRank::SpeciesSubgroup => "species subgroup",
TaxRank::Species => "species",
TaxRank::Subspecies => "subspecies",
TaxRank::Strain => "strain",
TaxRank::Synthetic => "synthetic",
TaxRank::Varietas => "varietas",
TaxRank::Subvarietas => "subvarietas",
TaxRank::Forma => "forma",
TaxRank::Unspecified => "no rank",
TaxRank::Clade => "clade",
TaxRank::Subforma => "subforma",
TaxRank::Cultivar => "cultivar",
TaxRank::Breed => "breed",
TaxRank::Strain => "strain",
TaxRank::Individual => "individual",
TaxRank::SeroGroup => "serogroup",
TaxRank::Unspecified => "no rank",
TaxRank::Biotype => "biotype",
TaxRank::Clade => "clade",
TaxRank::FormaSpecialis => "forma specialis",
TaxRank::Isolate => "isolate",
TaxRank::Serotype => "serotype",
TaxRank::Genotype => "genotype",
TaxRank::Morph => "morph",
TaxRank::Pathogroup => "pathogroup",
// TODO: not sure if we want to manually coerce everything like this?
_ => "no rank",
TaxRank::Synthetic => "synthetic",
}
}
}

impl fmt::Display for TaxRank {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}

impl FromStr for TaxRank {
type Err = Error;

Expand Down Expand Up @@ -195,8 +249,10 @@ impl FromStr for TaxRank {
"subclass" | "subclassis" => Ok(TaxRank::Subclass),
"infraclass" => Ok(TaxRank::Infraclass),
"parvclass" => Ok(TaxRank::Parvclass),
// note "division" may be either a TaxRank::Division (zoological)
// or synonym for TaxRank::Phylum (botanical) so we don't impl here
"superdivision" => Ok(TaxRank::Superdivision),
"division" => Ok(TaxRank::Division),
"subdivision" => Ok(TaxRank::Subdivision),
"infradivision" => Ok(TaxRank::Infradivision),
"superlegion" => Ok(TaxRank::Superlegion),
"legion" => Ok(TaxRank::Legion),
"sublegion" => Ok(TaxRank::Sublegion),
Expand All @@ -210,6 +266,7 @@ impl FromStr for TaxRank {
"magnorder" => Ok(TaxRank::Magnorder),
"grandorder" => Ok(TaxRank::Grandorder),
"mirorder" => Ok(TaxRank::Mirorder),
"series fish" => Ok(TaxRank::SeriesFish),
"order" | "ordo" => Ok(TaxRank::Order),
"nanorder" => Ok(TaxRank::Nanorder),
"hypoorder" => Ok(TaxRank::Hypoorder),
Expand All @@ -225,6 +282,8 @@ impl FromStr for TaxRank {
"hyperfamily" => Ok(TaxRank::Hyperfamily),
"superfamily" => Ok(TaxRank::Superfamily),
"epifamily" => Ok(TaxRank::Epifamily),
"series lepidoptera" => Ok(TaxRank::SeriesLepidoptera),
"group lepidoptera" => Ok(TaxRank::GroupLepidoptera),
"family" | "familia" => Ok(TaxRank::Family),
"subfamily" => Ok(TaxRank::Subfamily),
"infrafamily" => Ok(TaxRank::Infrafamily),
Expand All @@ -235,6 +294,7 @@ impl FromStr for TaxRank {
"genus" | "genera" => Ok(TaxRank::Genus),
"subgenus" => Ok(TaxRank::Subgenus),
"series" => Ok(TaxRank::Series),
"subseries botany" => Ok(TaxRank::SubseriesBotany),
"species group" => Ok(TaxRank::SpeciesGroup),
"species subgroup" => Ok(TaxRank::SpeciesSubgroup),
"species" => Ok(TaxRank::Species),
Expand All @@ -247,6 +307,7 @@ impl FromStr for TaxRank {
"cultivar" => Ok(TaxRank::Cultivar),
"breed" => Ok(TaxRank::Breed),
"strain" => Ok(TaxRank::Strain),
"individual" => Ok(TaxRank::Individual),
"serogroup" => Ok(TaxRank::SeroGroup),
"no rank" | "no_rank" => Ok(TaxRank::Unspecified),
"biotype" => Ok(TaxRank::Biotype),
Expand All @@ -262,105 +323,6 @@ impl FromStr for TaxRank {
}
}

impl fmt::Display for TaxRank {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let rank_str = match self {
TaxRank::Domain => "domain",
TaxRank::AcellularRoot => "acellular root",
TaxRank::CellularRoot => "cellular root",
TaxRank::Subdomain => "subdomain",
TaxRank::Realm => "realm",
TaxRank::Subrealm => "subrealm",
TaxRank::Hyperkingdom => "hyperkingdom",
TaxRank::Superkingdom => "superkingdom",
TaxRank::Kingdom => "kingdom",
TaxRank::Subkingdom => "subkingdom",
TaxRank::Infrakingdom => "infrakingdom",
TaxRank::Parvkingdom => "parvkingdom",
TaxRank::Superphylum => "superphylum",
TaxRank::Phylum => "phylum",
TaxRank::Subphylum => "subphylum",
TaxRank::Infraphylum => "infraphylum",
TaxRank::Microphylum => "microphylum",
TaxRank::Superclass => "superclass",
TaxRank::Class => "class",
TaxRank::Subclass => "subclass",
TaxRank::Infraclass => "infraclass",
TaxRank::Parvclass => "parvclass",
TaxRank::Superdivision => "superdivision",
TaxRank::Division => "division",
TaxRank::Subdivision => "subdivision",
TaxRank::Infradivision => "infradivision",
TaxRank::Superlegion => "superlegion",
TaxRank::Legion => "legion",
TaxRank::Sublegion => "sublegion",
TaxRank::Infralegion => "infralegion",
TaxRank::Supercohort => "supercohort",
TaxRank::Cohort => "cohort",
TaxRank::Subcohort => "subcohort",
TaxRank::Infracohort => "infracohort",
TaxRank::Superorder => "superorder",
TaxRank::Gigaorder => "gigaorder",
TaxRank::Magnorder => "magnorder",
TaxRank::Grandorder => "grandorder",
TaxRank::Mirorder => "mirorder",
TaxRank::SeriesFish => "series fish",
TaxRank::Order => "order",
TaxRank::Nanorder => "nanorder",
TaxRank::Hypoorder => "hypoorder",
TaxRank::Minorder => "minorder",
TaxRank::Suborder => "suborder",
TaxRank::Infraorder => "infraorder",
TaxRank::Parvorder => "parvorder",
TaxRank::Section => "section",
TaxRank::Subsection => "subsection",
TaxRank::Gigafamily => "gigafamily",
TaxRank::Megafamily => "megafamily",
TaxRank::Grandfamily => "grandfamily",
TaxRank::Hyperfamily => "hyperfamily",
TaxRank::Superfamily => "superfamily",
TaxRank::Epifamily => "epifamily",
TaxRank::SeriesLepidoptera => "series lepidoptera",
TaxRank::GroupLepidoptera => "group lepidoptera",
TaxRank::Family => "family",
TaxRank::Subfamily => "subfamily",
TaxRank::Infrafamily => "infrafamily",
TaxRank::Supertribe => "supertribe",
TaxRank::Tribe => "tribe",
TaxRank::Subtribe => "subtribe",
TaxRank::Infratribe => "infratribe",
TaxRank::Genus => "genus",
TaxRank::Subgenus => "subgenus",
TaxRank::Series => "series",
TaxRank::SubseriesBotany => "subseries botany",
TaxRank::SpeciesGroup => "species group",
TaxRank::SpeciesSubgroup => "species subgroup",
TaxRank::Species => "species",
TaxRank::Subspecies => "subspecies",
TaxRank::Varietas => "varietas",
TaxRank::Subvarietas => "subvarietas",
TaxRank::Forma => "forma",
TaxRank::Subforma => "subforma",
TaxRank::Cultivar => "cultivar",
TaxRank::Breed => "breed",
TaxRank::Strain => "strain",
TaxRank::Individual => "individual",
TaxRank::SeroGroup => "serogroup",
TaxRank::Unspecified => "no rank",
TaxRank::Biotype => "biotype",
TaxRank::Clade => "clade",
TaxRank::FormaSpecialis => "forma specialis",
TaxRank::Isolate => "isolate",
TaxRank::Serotype => "serotype",
TaxRank::Genotype => "genotype",
TaxRank::Morph => "morph",
TaxRank::Pathogroup => "pathogroup",
TaxRank::Synthetic => "synthetic",
};
write!(f, "{}", rank_str)
}
}

#[cfg(test)]
mod test {
use super::TaxRank;
Expand Down Expand Up @@ -461,7 +423,7 @@ mod test {
#[test]
fn test_str_to_rank() {
for rank in RANKS.iter() {
assert!(TaxRank::from_str(rank.to_ncbi_rank()).is_ok());
assert_eq!(TaxRank::from_str(rank.to_ncbi_rank()).unwrap(), *rank);
}
assert!(TaxRank::from_str("fake_data").is_err());
}
Expand All @@ -471,11 +433,11 @@ mod test {
for rank in RANKS.iter() {
let rank_str = rank.to_string();
assert!(!rank_str.is_empty());

let ncbi_str = rank.to_ncbi_rank();
if ncbi_str != "no rank" {
assert_eq!(ncbi_str, rank_str);
assert_eq!(rank.to_ncbi_rank(), rank_str);
if *rank != Unspecified {
assert_ne!(rank_str, "no rank");
}
}
assert_eq!(Domain.to_ncbi_rank(), "domain");
}
}
Loading