Repository: taxprofiler/taxpasta

Issue:
[Feature] Reverse the order of the current lineages
### Checklist

- [X] There are [no similar issues or pull requests](https://github.com/taxprofiler/taxpasta/issues) for this yet.

### Problem

Lineages are currently printed in order from taxon of interest to higher ranks (until root). This is in contrast to all other tools which print lineages from highest rank (superkingdom) to most specific.

### Solution

Reverse the order of lineages.

### Alternatives

One can find arguments for keeping either order but changing it seems to be the _de facto_ standard in the field.

### Anything else?

_No response_

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4c4a92..0678f92 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
     `merge` commands, which inserts a new column `rank_lineage` to results that
     contains semi-colon-separated strings with the ranks (#130).
 
+### Changed
+
+-   Reversed the order of lineages printed to output files (#131).
+
 ## [0.4.1] - (2023-07-13)
 
 ### Fixed
diff --git a/src/taxpasta/infrastructure/domain/service/taxopy_taxonomy_service.py b/src/taxpasta/infrastructure/domain/service/taxopy_taxonomy_service.py
index 9635340..4141e9f 100644
--- a/src/taxpasta/infrastructure/domain/service/taxopy_taxonomy_service.py
+++ b/src/taxpasta/infrastructure/domain/service/taxopy_taxonomy_service.py
@@ -73,7 +73,7 @@ class TaxopyTaxonomyService(TaxonomyService):
             taxon = taxopy.Taxon(taxid=taxonomy_id, taxdb=self._tax_db)
         except TaxidError:
             return None
-        return taxon.name_lineage
+        return list(reversed(taxon.name_lineage))
 
     def get_taxon_identifier_lineage(self, taxonomy_id: int) -> Optional[List[int]]:
         """Return the lineage of a given taxonomy identifier as identifiers."""
@@ -81,7 +81,7 @@ class TaxopyTaxonomyService(TaxonomyService):
             taxon = taxopy.Taxon(taxid=taxonomy_id, taxdb=self._tax_db)
         except TaxidError:
             return None
-        return taxon.taxid_lineage
+        return list(reversed(taxon.taxid_lineage))
 
     def get_taxon_rank_lineage(self, taxonomy_id: int) -> Optional[List[str]]:
         """Return the lineage of a given taxonomy identifier as ranks."""
@@ -89,7 +89,7 @@ class TaxopyTaxonomyService(TaxonomyService):
             taxon = taxopy.Taxon(taxid=taxonomy_id, taxdb=self._tax_db)
         except TaxidError:
             return None
-        return list(taxon.rank_name_dictionary.keys())
+        return list(reversed(taxon.rank_name_dictionary.keys()))
 
     def add_name(self, table: DataFrame[ResultTable]) -> DataFrame[ResultTable]:
         """Add a column for the taxon name to the given table."""
@@ -123,11 +123,10 @@ class TaxopyTaxonomyService(TaxonomyService):
 
     def _name_lineage_as_str(self, taxonomy_id: int) -> Optional[str]:
         """Return the lineage of a taxon as concatenated names."""
-        try:
-            taxon = taxopy.Taxon(taxid=taxonomy_id, taxdb=self._tax_db)
-        except TaxidError:
+        if lineage := self.get_taxon_name_lineage(taxonomy_id):
+            return ";".join(lineage)
+        else:
             return None
-        return ";".join(taxon.name_lineage)
 
     def add_identifier_lineage(
         self, table: DataFrame[ResultTable]
@@ -143,11 +142,10 @@ class TaxopyTaxonomyService(TaxonomyService):
 
     def _taxid_lineage_as_str(self, taxonomy_id: int) -> Optional[str]:
         """Return the lineage of a taxon as concatenated identifiers."""
-        try:
-            taxon = taxopy.Taxon(taxid=taxonomy_id, taxdb=self._tax_db)
-        except TaxidError:
+        if lineage := self.get_taxon_identifier_lineage(taxonomy_id):
+            return ";".join(str(tax_id) for tax_id in lineage)
+        else:
             return None
-        return ";".join([str(tax_id) for tax_id in taxon.taxid_lineage])
 
     def add_rank_lineage(self, table: DataFrame[ResultTable]) -> DataFrame[ResultTable]:
         """Add a column for the taxon lineage as ranks to the given table."""
@@ -161,11 +159,10 @@ class TaxopyTaxonomyService(TaxonomyService):
 
     def _rank_lineage_as_str(self, taxonomy_id: int) -> Optional[str]:
         """Return the rank lineage of a taxon as concatenated identifiers."""
-        try:
-            taxon = taxopy.Taxon(taxid=taxonomy_id, taxdb=self._tax_db)
-        except TaxidError:
+        if lineage := self.get_taxon_rank_lineage(taxonomy_id):
+            return ";".join(lineage)
+        else:
             return None
-        return ";".join(taxon.rank_name_dictionary.keys())
 
     def summarise_at(
         self, profile: DataFrame[StandardProfile], rank: str


Test patch:
diff --git a/tests/unit/infrastructure/domain/service/test_taxopy_taxonomy_service.py b/tests/unit/infrastructure/domain/service/test_taxopy_taxonomy_service.py
index 5109384..1c3e2ab 100644
--- a/tests/unit/infrastructure/domain/service/test_taxopy_taxonomy_service.py
+++ b/tests/unit/infrastructure/domain/service/test_taxopy_taxonomy_service.py
@@ -82,14 +82,14 @@ def test_get_taxon_rank(tax_service: TaxopyTaxonomyService, tax_id: int, expecte
         (
             86398254,
             [
-                "Pseudomonadales",
-                "Gammaproteobacteria",
-                "Proteobacteria",
-                "Bacteria",
                 "root",
+                "Bacteria",
+                "Proteobacteria",
+                "Gammaproteobacteria",
+                "Pseudomonadales",
             ],
         ),
-        (1199096325, ["Saccharomycetes", "Ascomycota", "Eukaryota", "root"]),
+        (1199096325, ["root", "Eukaryota", "Ascomycota", "Saccharomycetes"]),
     ],
 )
 def test_get_taxon_name_lineage(
@@ -104,8 +104,8 @@ def test_get_taxon_name_lineage(
     [
         (1, [1]),
         (42, None),
-        (86398254, [86398254, 329474883, 1641076285, 609216830, 1]),
-        (1199096325, [1199096325, 432158898, 476817098, 1]),
+        (86398254, [1, 609216830, 1641076285, 329474883, 86398254]),
+        (1199096325, [1, 476817098, 432158898, 1199096325]),
     ],
 )
 def test_get_taxon_identifier_lineage(
@@ -120,8 +120,8 @@ def test_get_taxon_identifier_lineage(
     [
         (1, []),
         (42, None),
-        (86398254, ["order", "class", "phylum", "superkingdom"]),
-        (1199096325, ["class", "phylum", "superkingdom"]),
+        (86398254, ["superkingdom", "phylum", "class", "order"]),
+        (1199096325, ["superkingdom", "phylum", "class"]),
     ],
 )
 def test_get_taxon_rank_lineage(
@@ -145,9 +145,9 @@ def test_get_taxon_rank_lineage(
                             [
                                 "root",
                                 None,
-                                "Pseudomonadales;Gammaproteobacteria;Proteobacteria;"
-                                "Bacteria;root",
-                                "Saccharomycetes;Ascomycota;Eukaryota;root",
+                                "root;Bacteria;Proteobacteria;Gammaproteobacteria;"
+                                "Pseudomonadales",
+                                "root;Eukaryota;Ascomycota;Saccharomycetes",
                             ],
                         ),
                     ]
@@ -177,8 +177,8 @@ def test_add_name_lineage(
                             [
                                 "1",
                                 None,
-                                "86398254;329474883;1641076285;609216830;1",
-                                "1199096325;432158898;476817098;1",
+                                "1;609216830;1641076285;329474883;86398254",
+                                "1;476817098;432158898;1199096325",
                             ],
                         ),
                     ]
@@ -206,10 +206,10 @@ def test_add_identifier_lineage(
                         (
                             "rank_lineage",
                             [
-                                "",
                                 None,
-                                "order;class;phylum;superkingdom",
-                                "class;phylum;superkingdom",
+                                None,
+                                "superkingdom;phylum;class;order",
+                                "superkingdom;phylum;class",
                             ],
                         ),
                     ]