update api documentation

This commit is contained in:
Eric Coissac
2024-11-16 05:59:41 +01:00
parent 03f4e88a17
commit f5d79d0bc4
13 changed files with 372 additions and 62 deletions

View File

@ -4,6 +4,16 @@ import (
"regexp"
)
// IFilterOnName filters the Taxon instances in the Taxonomy based on the specified name.
// If strict is true, it looks for an exact match of the name. If false, it allows for pattern matching.
// It returns a new ITaxon iterator containing the filtered results.
//
// Parameters:
// - name: The name to filter Taxon instances by.
// - strict: A boolean indicating whether to perform strict matching (true) or pattern matching (false).
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances that match the specified name.
func (taxonomy *Taxonomy) IFilterOnName(name string, strict bool) *ITaxon {
if strict {
nodes, ok := taxonomy.index[taxonomy.names.Innerize(name)]
@ -18,6 +28,16 @@ func (taxonomy *Taxonomy) IFilterOnName(name string, strict bool) *ITaxon {
return taxonomy.Iterator().IFilterOnName(name, strict)
}
// IFilterOnName filters the Taxon instances in the iterator based on the specified name.
// If strict is true, it looks for an exact match of the name. If false, it allows for pattern matching.
// It returns a new ITaxon iterator containing the filtered results.
//
// Parameters:
// - name: The name to filter Taxon instances by.
// - strict: A boolean indicating whether to perform strict matching (true) or pattern matching (false).
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances that match the specified name.
func (iterator *ITaxon) IFilterOnName(name string, strict bool) *ITaxon {
newIterator := NewITaxon()
sentTaxa := make(map[*string]bool)

View File

@ -1,5 +1,15 @@
package obitax
// IFilterOnTaxRank filters the iterator to include only those Taxon instances
// that match the specified taxonomic rank. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - rank: A string representing the taxonomic rank to filter by.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that have the specified taxonomic rank.
func (iterator *ITaxon) IFilterOnTaxRank(rank string) *ITaxon {
newIter := NewITaxon()
var prank *string
@ -24,14 +34,44 @@ func (iterator *ITaxon) IFilterOnTaxRank(rank string) *ITaxon {
return newIter
}
// IFilterOnTaxRank filters the TaxonSet to include only those Taxon instances
// that match the specified taxonomic rank. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - rank: A string representing the taxonomic rank to filter by.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that have the specified taxonomic rank.
func (set *TaxonSet) IFilterOnTaxRank(rank string) *ITaxon {
return set.Iterator().IFilterOnTaxRank(rank)
}
// IFilterOnTaxRank filters the TaxonSlice to include only those Taxon instances
// that match the specified taxonomic rank. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - rank: A string representing the taxonomic rank to filter by.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that have the specified taxonomic rank.
func (slice *TaxonSlice) IFilterOnTaxRank(rank string) *ITaxon {
return slice.Iterator().IFilterOnTaxRank(rank)
}
// IFilterOnTaxRank filters the Taxonomy to include only those Taxon instances
// that match the specified taxonomic rank. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - rank: A string representing the taxonomic rank to filter by.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that have the specified taxonomic rank.
func (taxonomy *Taxonomy) IFilterOnTaxRank(rank string) *ITaxon {
return taxonomy.Iterator().IFilterOnTaxRank(rank)
}

View File

@ -1,5 +1,15 @@
package obitax
// IFilterOnSubcladeOf filters the iterator to include only those Taxon instances
// that are subclades of the specified Taxon. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - taxon: A pointer to the Taxon to filter subclades against.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that are subclades of the specified Taxon.
func (iterator *ITaxon) IFilterOnSubcladeOf(taxon *Taxon) *ITaxon {
newIter := NewITaxon()
@ -16,26 +26,66 @@ func (iterator *ITaxon) IFilterOnSubcladeOf(taxon *Taxon) *ITaxon {
return newIter
}
// IFilterOnSubcladeOf filters the TaxonSet to include only those Taxon instances
// that are subclades of the specified Taxon. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - taxon: A pointer to the Taxon to filter subclades against.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that are subclades of the specified Taxon.
func (set *TaxonSet) IFilterOnSubcladeOf(taxon *Taxon) *ITaxon {
return set.Iterator().IFilterOnSubcladeOf(taxon)
}
// IFilterOnSubcladeOf filters the TaxonSlice to include only those Taxon instances
// that are subclades of the specified Taxon. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - taxon: A pointer to the Taxon to filter subclades against.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that are subclades of the specified Taxon.
func (slice *TaxonSlice) IFilterOnSubcladeOf(taxon *Taxon) *ITaxon {
return slice.Iterator().IFilterOnSubcladeOf(taxon)
}
// IFilterOnSubcladeOf filters the Taxonomy to include only those Taxon instances
// that are subclades of the specified Taxon. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - taxon: A pointer to the Taxon to filter subclades against.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that are subclades of the specified Taxon.
func (taxonomy *Taxonomy) IFilterOnSubcladeOf(taxon *Taxon) *ITaxon {
return taxonomy.Iterator().IFilterOnSubcladeOf(taxon)
}
// IFilterBelongingSubclades filters the iterator to include only those Taxon instances
// that belong to any of the specified subclades. It returns a new ITaxon iterator
// containing the filtered results.
//
// Parameters:
// - clades: A pointer to a TaxonSet containing the subclades to filter against.
//
// Returns:
// - A pointer to a new ITaxon iterator containing only the Taxon instances
// that belong to the specified subclades. If the clades set is empty,
// it returns the original iterator.
func (iterator *ITaxon) IFilterBelongingSubclades(clades *TaxonSet) *ITaxon {
if clades.Len() == 0 {
return iterator
}
// Considers the second simplest case when only
// a single subclase is provided
// a single subclade is provided
if clades.Len() == 1 {
keys := make([]*string, 0, len(clades.set))
for k := range clades.set {

View File

@ -5,12 +5,12 @@ import "sync"
// InnerString is a struct that holds a map of strings and a read-write lock for concurrent access.
// The index map is used to store key-value pairs of strings.
type InnerString struct {
index map[string]*string
lock sync.RWMutex
index map[string]*string // Map to store string values
lock sync.RWMutex // Read-write lock for concurrent access
}
// NewInnerString creates a new instance of InnerString.
// The lock is set to false.
// It initializes the index map and prepares the lock for use.
func NewInnerString() *InnerString {
return &InnerString{
index: make(map[string]*string),
@ -18,14 +18,14 @@ func NewInnerString() *InnerString {
}
// Innerize stores the given value in the index map if it is not already present.
// It returns the value associated with the key, which is either the newly stored value
// It returns the pointer to the string associated with the key, which is either the newly stored value
// or the existing value if it was already present in the map.
//
// Parameters:
// - value: The string value to be stored in the index map.
//
// Returns:
// - The string value associated with the key.
// - A pointer to the string value associated with the key.
func (i *InnerString) Innerize(value string) *string {
i.lock.Lock()
defer i.lock.Unlock()
@ -38,6 +38,7 @@ func (i *InnerString) Innerize(value string) *string {
return s
}
// Slice returns a slice of strings containing all the values stored in the index map.
func (i *InnerString) Slice() []string {
rep := make([]string, len(i.index))
j := 0

View File

@ -2,8 +2,16 @@ package obitax
import log "github.com/sirupsen/logrus"
// IsSubCladeOf checks if the current Taxon is a subclade of the specified parent Taxon.
// It returns true if the current Taxon is a descendant of the parent Taxon in the taxonomy hierarchy.
//
// Parameters:
// - parent: A pointer to the parent Taxon to check against.
//
// Returns:
// - A boolean indicating whether the current Taxon is a subclade of the parent Taxon.
// - Logs a fatal error if the two taxa do not belong to the same taxonomy.
func (taxon *Taxon) IsSubCladeOf(parent *Taxon) bool {
if taxon.Taxonomy != parent.Taxonomy {
log.Fatalf(
"Both taxa %s and %s must belong to the same taxonomy",
@ -21,6 +29,15 @@ func (taxon *Taxon) IsSubCladeOf(parent *Taxon) bool {
return false
}
// IsBelongingSubclades checks if the current Taxon belongs to any of the specified subclades.
// It traverses up the taxonomy hierarchy to determine if the current Taxon or any of its ancestors
// belong to the provided TaxonSet.
//
// Parameters:
// - clades: A pointer to a TaxonSet containing the subclades to check against.
//
// Returns:
// - A boolean indicating whether the current Taxon or any of its ancestors belong to the specified subclades.
func (taxon *Taxon) IsBelongingSubclades(clades *TaxonSet) bool {
ok := clades.Contains(taxon.Node.id)

View File

@ -1,22 +1,28 @@
package obitax
// ITaxon represents an iterator for traversing Taxon instances.
// It provides methods to retrieve the next Taxon and check if the iteration is finished.
type ITaxon struct {
source chan *Taxon
current *Taxon
finished bool
p_finished *bool
source chan *Taxon // Channel to receive Taxon instances
current *Taxon // Current Taxon instance
finished bool // Indicates if the iteration is finished
p_finished *bool // Pointer to the finished status
}
// NewITaxon creates a new ITaxon iterator instance and initializes its fields.
func NewITaxon() *ITaxon {
i := ITaxon{
source: make(chan *Taxon),
current: nil,
finished: false,
p_finished: nil}
p_finished: nil,
}
i.p_finished = &i.finished
return &i
}
// Iterator creates a new ITaxon iterator for the TaxonSet.
// It starts a goroutine to send Taxon instances from the set to the iterator's source channel.
func (set *TaxonSet) Iterator() *ITaxon {
i := NewITaxon()
@ -33,6 +39,8 @@ func (set *TaxonSet) Iterator() *ITaxon {
return i
}
// Iterator creates a new ITaxon iterator for the TaxonSlice.
// It starts a goroutine to send Taxon instances from the slice to the iterator's source channel.
func (set *TaxonSlice) Iterator() *ITaxon {
i := NewITaxon()
@ -49,10 +57,13 @@ func (set *TaxonSlice) Iterator() *ITaxon {
return i
}
func (taxonmy *Taxonomy) Iterator() *ITaxon {
return taxonmy.nodes.Iterator()
// Iterator creates a new ITaxon iterator for the Taxonomy's nodes.
func (taxonomy *Taxonomy) Iterator() *ITaxon {
return taxonomy.nodes.Iterator()
}
// Next advances the iterator to the next Taxon instance.
// It returns true if there is a next Taxon, and false if the iteration is finished.
func (iterator *ITaxon) Next() bool {
if *(iterator.p_finished) {
return false
@ -69,20 +80,19 @@ func (iterator *ITaxon) Next() bool {
return false
}
// The 'Get' method returns the instance of *TaxNode
// currently pointed by the iterator. You have to use the
// 'Next' method to move to the next entry before calling
// 'Get' to retreive the following instance.
// Get returns the current Taxon instance pointed to by the iterator.
// You must call 'Next' before calling 'Get' to retrieve the next instance.
func (iterator *ITaxon) Get() *Taxon {
return iterator.current
}
// Finished returns 'true' value if no more data is available
// from the iterator.
// Finished returns true if no more data is available from the iterator.
func (iterator *ITaxon) Finished() bool {
return *iterator.p_finished
}
// Split creates a new ITaxon iterator that shares the same source channel
// and finished status as the original iterator.
func (iterator *ITaxon) Split() *ITaxon {
return &ITaxon{
source: iterator.source,

View File

@ -1,16 +1,35 @@
package obitax
import (
log "github.com/sirupsen/logrus"
"fmt"
)
// LCA computes the Lowest Common Ancestor (LCA) of two Taxon instances.
// It traverses the paths from both taxa to the root and finds the deepest
// common node in the taxonomy hierarchy.
//
// Parameters:
// - t2: A pointer to another Taxon instance to find the LCA with.
//
// Returns:
// - A pointer to the Taxon representing the LCA of the two taxa, or an error
// if either of the taxa is nil, if they are not in the same taxonomy, or
// if the taxonomy is unrooted.
func (t1 *Taxon) LCA(t2 *Taxon) (*Taxon, error) {
if t1 == nil {
log.Panicf("Try to get LCA of nil taxon")
if t1 == nil || t1.Node == nil {
return nil, fmt.Errorf("try to get LCA of nil taxon")
}
if t2 == nil {
log.Panicf("Try to get LCA of nil taxon")
if t2 == nil || t2.Node == nil {
return nil, fmt.Errorf("try to get LCA of nil taxon")
}
if t1.Taxonomy != t2.Taxonomy {
return nil, fmt.Errorf("taxa are not in the same taxonomy")
}
if !t1.Taxonomy.HasRoot() {
return nil, fmt.Errorf("taxa belong to an unrooted taxonomy")
}
p1 := t1.Path()

View File

@ -11,8 +11,8 @@ import (
// it belongs to and the specific taxon node information.
//
// Fields:
// - Taxonomy: A pointer to the Taxonomy[T] instance that this taxon is part of.
// - Node: A pointer to the TaxNode[T] instance representing the specific taxon.
// - Taxonomy: A pointer to the Taxonomy instance that this taxon is part of.
// - Node: A pointer to the TaxNode instance representing the specific taxon.
type Taxon struct {
Taxonomy *Taxonomy
Node *TaxNode
@ -42,6 +42,14 @@ func (taxon *Taxon) ScientificName() string {
return taxon.Node.ScientificName()
}
// Name retrieves the name of the Taxon based on the specified class.
// It uses the taxonomy's name classes to format the name appropriately.
//
// Parameters:
// - class: A string representing the name class to use for retrieval.
//
// Returns:
// - The name of the taxon as a string.
func (taxon *Taxon) Name(class string) string {
if taxon == nil {
return "NA"
@ -50,6 +58,14 @@ func (taxon *Taxon) Name(class string) string {
return taxon.Node.Name(pclass)
}
// IsNameEqual checks if the given name is equal to the name of the Taxon.
// It compares the provided name with the name stored in the TaxNode.
//
// Parameters:
// - name: A string representing the name to compare against.
//
// Returns:
// - A boolean indicating whether the names are equal.
func (taxon *Taxon) IsNameEqual(name string) bool {
if taxon == nil {
return false
@ -58,6 +74,13 @@ func (taxon *Taxon) IsNameEqual(name string) bool {
return taxon.Node.IsNameEqual(name)
}
// IsNameMatching checks if the name of the Taxon matches the given regular expression pattern.
//
// Parameters:
// - pattern: A pointer to a compiled regular expression to match against the taxon's name.
//
// Returns:
// - A boolean indicating whether the taxon's name matches the specified pattern.
func (taxon *Taxon) IsNameMatching(pattern *regexp.Regexp) bool {
if taxon == nil {
return false
@ -66,6 +89,12 @@ func (taxon *Taxon) IsNameMatching(pattern *regexp.Regexp) bool {
return taxon.Node.IsNameMatching(pattern)
}
// SetName sets the name of the Taxon based on the provided name and class.
// It logs a panic if the taxon pointer is nil.
//
// Parameters:
// - name: A string representing the new name to set for the taxon.
// - class: A string representing the name class to associate with the taxon.
func (taxon *Taxon) SetName(name, class string) {
if taxon == nil {
log.Panicf("nil taxon pointer for name %s [%s]", name, class)
@ -76,6 +105,11 @@ func (taxon *Taxon) SetName(name, class string) {
taxon.Node.SetName(pname, pclass)
}
// IsRoot checks if the Taxon is the root of the taxonomy.
// It returns true if the taxon is nil or if it matches the root node of the taxonomy.
//
// Returns:
// - A boolean indicating whether the Taxon is the root of the taxonomy.
func (taxon *Taxon) IsRoot() bool {
if taxon == nil {
return true
@ -101,7 +135,7 @@ func (taxon *Taxon) Rank() string {
// to create a new Taxon instance representing the parent taxon.
//
// Returns:
// - A pointer to the parent Taxon[T]. If the parent does not exist, it returns
// - A pointer to the parent Taxon. If the parent does not exist, it returns
// a Taxon with a nil Node.
func (taxon *Taxon) Parent() *Taxon {
if taxon == nil {
@ -120,7 +154,6 @@ func (taxon *Taxon) Parent() *Taxon {
// is called with each Taxon in the path from the current taxon to the root. If the
// taxonomy has no root node, the method logs a fatal error and terminates the program.
func (taxon *Taxon) IPath() iter.Seq[*Taxon] {
if taxon.Taxonomy.root == nil {
log.Fatalf("Taxon[%v].IPath(): Taxonomy has no root node", taxon.Taxonomy.name)
}
@ -140,13 +173,13 @@ func (taxon *Taxon) IPath() iter.Seq[*Taxon] {
}
}
// Path returns a slice of TaxNode[T] representing the path from the current Taxon
// Path returns a slice of TaxNode representing the path from the current Taxon
// to the root Taxon in the associated Taxonomy. It collects all the nodes in the path
// using the IPath method and returns them as a TaxonSlice.
//
// Returns:
// - A pointer to a TaxonSlice[T] containing the TaxNode[T] instances in the path
// from the current taxon to the root.
// - A pointer to a TaxonSlice containing the TaxNode instances in the path
// from the current taxon to the root. If the taxon is nil, it returns nil.
func (taxon *Taxon) Path() *TaxonSlice {
if taxon == nil {
return nil
@ -196,7 +229,7 @@ func (taxon *Taxon) HasRankDefined(rank string) bool {
// - rank: A string representing the rank to search for (e.g., "species", "genus").
//
// Returns:
// - A pointer to the Taxon[T] that matches the specified rank, or nil if no such taxon exists
// - A pointer to the Taxon that matches the specified rank, or nil if no such taxon exists
// in the path to the root.
func (taxon *Taxon) TaxonAtRank(rank string) *Taxon {
if taxon == nil {
@ -219,7 +252,7 @@ func (taxon *Taxon) TaxonAtRank(rank string) *Taxon {
// the matching Taxon.
//
// Returns:
// - A pointer to the Taxon[T] that matches the "species" rank, or nil if no such taxon
// - A pointer to the Taxon that matches the "species" rank, or nil if no such taxon
// exists in the path to the root.
func (taxon *Taxon) Species() *Taxon {
return taxon.TaxonAtRank("species")
@ -230,7 +263,7 @@ func (taxon *Taxon) Species() *Taxon {
// the matching Taxon.
//
// Returns:
// - A pointer to the Taxon[T] that matches the "genus" rank, or nil if no such taxon
// - A pointer to the Taxon that matches the "genus" rank, or nil if no such taxon
// exists in the path to the root.
func (taxon *Taxon) Genus() *Taxon {
return taxon.TaxonAtRank("genus")
@ -241,7 +274,7 @@ func (taxon *Taxon) Genus() *Taxon {
// the matching Taxon.
//
// Returns:
// - A pointer to the Taxon[T] that matches the "family" rank, or nil if no such taxon
// - A pointer to the Taxon that matches the "family" rank, or nil if no such taxon
// exists in the path to the root.
func (taxon *Taxon) Family() *Taxon {
return taxon.TaxonAtRank("family")

View File

@ -11,12 +11,12 @@ import (
// scientific name, and alternate names.
//
// Fields:
// - id: The unique identifier of the taxon of type T.
// - parent: The identifier of the parent taxon of type T.
// - rank: The rank of the taxon (e.g., species, genus).
// - id: A pointer to the unique identifier of the taxon of type T.
// - parent: A pointer to the identifier of the parent taxon of type T.
// - rank: A pointer to the rank of the taxon (e.g., species, genus).
// - scientificname: A pointer to a string representing the scientific name of the taxon.
// - alternatenames: A pointer to a map of alternate names for the taxon, where the key is
// a string representing the class name and the value is a pointer to a string
// a pointer to a string representing the class name and the value is a pointer to a string
// representing the name.
type TaxNode struct {
id *string
@ -45,7 +45,7 @@ func (node *TaxNode) String(taxonomyCode string) string {
// It retrieves the identifier of type T associated with the taxon node.
//
// Returns:
// - The unique identifier of the taxon node of type T.
// - A pointer to the unique identifier of the taxon node of type T.
func (node *TaxNode) Id() *string {
return node.id
}
@ -54,7 +54,7 @@ func (node *TaxNode) Id() *string {
// It retrieves the parent identifier of type T associated with the taxon node.
//
// Returns:
// - The identifier of the parent taxon of type T.
// - A pointer to the identifier of the parent taxon of type T.
func (node *TaxNode) ParentId() *string {
return node.parent
}
@ -64,8 +64,9 @@ func (node *TaxNode) ParentId() *string {
//
// Returns:
// - The scientific name of the taxon as a string.
// - Note: This method assumes that scientificname is not nil;
// if it may be nil, additional error handling should be implemented.
// - If the scientific name is nil, it returns "NA".
// - Note: This method assumes that the TaxNode itself is not nil; if it may be nil,
// additional error handling should be implemented.
func (node *TaxNode) ScientificName() string {
if node == nil {
return "NA"
@ -77,18 +78,18 @@ func (node *TaxNode) ScientificName() string {
}
// Name retrieves the name of the TaxNode based on the specified class.
// If the class is "scientificname", it returns the scientific name of the taxon.
// If the class is "scientific name", it returns the scientific name of the taxon.
// If the class corresponds to an alternate name, it retrieves that name from the alternatenames map.
// If the class is not recognized or if no alternate names exist, it returns an empty string.
//
// Parameters:
// - class: A string representing the class of name to retrieve (e.g., "scientificname" or an alternate name class).
// - class: A pointer to a string representing the class of name to retrieve
// (e.g., "scientific name" or an alternate name class).
//
// Returns:
// - The name of the taxon as a string. If the class is not recognized or if no name is available,
// an empty string is returned.
func (node *TaxNode) Name(class *string) string {
if *class == "scientific name" {
return *node.scientificname
}
@ -106,6 +107,14 @@ func (node *TaxNode) Name(class *string) string {
return ""
}
// SetName sets the name of the TaxNode based on the specified class.
// If the class is "scientific name", it updates the scientific name of the taxon.
// If the class corresponds to an alternate name, it adds or updates that name in the alternatenames map.
//
// Parameters:
// - name: A pointer to a string representing the name to set.
// - class: A pointer to a string representing the class of name to set
// (e.g., "scientific name" or an alternate name class).
func (node *TaxNode) SetName(name, class *string) {
if node == nil {
log.Panic("Cannot set name of nil TaxNode")

View File

@ -1,3 +1,10 @@
/*
Package obitax provides functionality for managing taxonomic data structures,
including hierarchical classifications of taxa. It includes the Taxonomy struct,
which represents a taxonomy and provides methods for working with taxon identifiers
and retrieving information about taxa.
*/
package obitax
import (
@ -14,9 +21,13 @@ import (
// Fields:
// - name: The name of the taxonomy.
// - code: A unique code representing the taxonomy.
// - ids: A pointer to an InnerString instance that holds the taxon identifiers.
// - ranks: A pointer to an InnerString instance that holds the ranks of the taxa.
// - nameclasses: A pointer to an InnerString instance that holds the name classes.
// - names: A pointer to an InnerString instance that holds the names of the taxa.
// - nodes: A pointer to a TaxonSet containing all the nodes (taxa) in the taxonomy.
// - root: A pointer to the root TaxNode of the taxonomy.
// - matcher: A regular expression used for validating taxon identifiers.
// - index: A map that indexes taxa by their string representation for quick access.
type Taxonomy struct {
name string
@ -37,14 +48,13 @@ type Taxonomy struct {
// Parameters:
// - name: The name of the taxonomy to be created.
// - code: A unique code representing the taxonomy.
// - codeCharacters: A string representing valid characters for the taxon identifiers.
//
// Returns:
// - A pointer to the newly created Taxonomy instance.
func NewTaxonomy(name, code, codeCharacters string) *Taxonomy {
set := make(map[*string]*TaxNode)
// codeCharacters := "[[:alnum:]]" // [[:digit:]]
matcher := regexp.MustCompile(fmt.Sprintf("^[[:blank:]]*(%s:)?(%s+)", code, codeCharacters))
taxonomy := &Taxonomy{
@ -119,7 +129,7 @@ func (taxonomy *Taxonomy) TaxidSting(id string) (string, error) {
// - taxid: A string representation of the taxon identifier to be retrieved.
//
// Returns:
// - A pointer to the Taxon[T] instance associated with the provided taxid.
// - A pointer to the Taxon instance associated with the provided taxid.
// - If the taxid is unknown, the method will log a fatal error.
func (taxonomy *Taxonomy) Taxon(taxid string) *Taxon {
id, err := taxonomy.Id(taxid)
@ -139,11 +149,11 @@ func (taxonomy *Taxonomy) Taxon(taxid string) *Taxon {
return taxon
}
// TaxonSet returns the set of taxon nodes contained within the Taxonomy.
// AsTaxonSet returns the set of taxon nodes contained within the Taxonomy.
// It provides access to the underlying collection of taxon nodes for further operations.
//
// Returns:
// - A pointer to the TaxonSet[T] representing the collection of taxon nodes in the taxonomy.
// - A pointer to the TaxonSet representing the collection of taxon nodes in the taxonomy.
func (taxonomy *Taxonomy) AsTaxonSet() *TaxonSet {
return taxonomy.nodes
}
@ -168,7 +178,7 @@ func (taxonomy *Taxonomy) Len() int {
// - replace: A boolean indicating whether to replace an existing taxon with the same taxid.
//
// Returns:
// - A pointer to the newly created Taxon[T] instance.
// - A pointer to the newly created Taxon instance.
// - An error if the taxon cannot be added (e.g., it already exists and replace is false).
func (taxonomy *Taxonomy) AddTaxon(taxid, parent string, rank string, isRoot bool, replace bool) (*Taxon, error) {
@ -204,6 +214,19 @@ func (taxonomy *Taxonomy) AddTaxon(taxid, parent string, rank string, isRoot boo
}, nil
}
// AddAlias adds an alias for an existing taxon in the taxonomy.
// It associates a new taxon identifier with an existing taxon identifier,
// allowing for alternative names to be used. If specified, it can replace
// an existing alias.
//
// Parameters:
// - newtaxid: The new identifier to be added as an alias.
// - oldtaxid: The existing identifier of the taxon to which the alias is added.
// - replace: A boolean indicating whether to replace an existing alias with the same newtaxid.
//
// Returns:
// - A pointer to the Taxon associated with the oldtaxid.
// - An error if the alias cannot be added (e.g., the old taxon does not exist).
func (taxonomy *Taxonomy) AddAlias(newtaxid, oldtaxid string, replace bool) (*Taxon, error) {
newid, err := taxonomy.Id(newtaxid)
@ -241,14 +264,56 @@ func (taxonomy *Taxonomy) RankList() []string {
return taxonomy.ranks.Slice()
}
// Index returns a pointer to the map that indexes taxa by their string representation.
// This allows for quick access to taxon sets based on their identifiers.
//
// Returns:
// - A pointer to the map that indexes taxa in the taxonomy.
func (taxonomy *Taxonomy) Index() *map[*string]*TaxonSet {
return &(taxonomy.index)
}
// Name returns the name of the taxonomy.
//
// Returns:
// - A string representing the name of the taxonomy.
func (taxonomy *Taxonomy) Name() string {
return taxonomy.name
}
// Code returns the unique code representing the taxonomy.
//
// Returns:
// - A string representing the unique code of the taxonomy.
func (taxonomy *Taxonomy) Code() string {
return taxonomy.code
}
// SetRoot sets the root taxon for the taxonomy.
// It associates the provided Taxon instance as the root of the taxonomy.
//
// Parameters:
// - root: A pointer to the Taxon instance to be set as the root.
func (taxonomy *Taxonomy) SetRoot(root *Taxon) {
taxonomy.root = root.Node
}
// Root returns the root taxon of the taxonomy.
// It returns a pointer to a Taxon instance associated with the root node.
//
// Returns:
// - A pointer to the Taxon instance representing the root of the taxonomy.
func (taxonomy *Taxonomy) Root() *Taxon {
return &Taxon{
Taxonomy: taxonomy,
Node: taxonomy.root,
}
}
// HasRoot checks if the Taxonomy has a root node defined.
//
// Returns:
// - A boolean indicating whether the Taxonomy has a root node (true) or not (false).
func (taxonomy *Taxonomy) HasRoot() bool {
return taxonomy.root != nil
}

View File

@ -1,4 +1,10 @@
// Package obitax provides functionality for managing taxonomic data structures.
/*
Package obitax provides functionality for managing taxonomic data structures,
specifically for representing and manipulating collections of taxa within a taxonomy.
It includes the TaxonSet structure, which holds mappings of taxon identifiers to their
corresponding TaxNode instances, along with methods for managing and querying these taxa.
*/
package obitax
import log "github.com/sirupsen/logrus"
@ -17,6 +23,11 @@ type TaxonSet struct {
taxonomy *Taxonomy
}
// NewTaxonSet creates a new TaxonSet associated with the given Taxonomy.
// It initializes the set as an empty map and sets the alias count to zero.
//
// Returns:
// - A pointer to the newly created TaxonSet.
func (taxonomy *Taxonomy) NewTaxonSet() *TaxonSet {
return &TaxonSet{
set: make(map[*string]*TaxNode),
@ -77,10 +88,16 @@ func (set *TaxonSet) Insert(node *TaxNode) {
set.set[node.id] = node
}
// InsertTaxon adds a Taxon to the TaxonSet. It verifies that the Taxon belongs
// to the same Taxonomy as the TaxonSet before insertion. If they do not match,
// it logs a fatal error and terminates the program.
//
// Parameters:
// - taxon: A pointer to the Taxon instance to be added to the TaxonSet.
func (set *TaxonSet) InsertTaxon(taxon *Taxon) {
if set.taxonomy != taxon.Taxonomy {
log.Fatalf(
"Cannot insert taxon %s into taxon set belonging %s taxonomy",
"Cannot insert taxon %s into taxon set belonging to %s taxonomy",
taxon.String(),
set.taxonomy.name,
)

View File

@ -1,3 +1,13 @@
/*
Package obitax provides functionality for handling taxonomic data structures,
specifically for representing and manipulating collections of taxon nodes
within a taxonomy.
The primary data structure is the TaxonSlice, which encapsulates a slice of
TaxNode instances and provides methods for accessing, counting, and
formatting these nodes.
*/
package obitax
import (
@ -7,17 +17,26 @@ import (
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiutils"
)
// TaxonSlice represents a slice of TaxNode[T] instances within a taxonomy.
// TaxonSlice represents a slice of TaxNode instances within a taxonomy.
// It encapsulates a collection of taxon nodes and the taxonomy they belong to.
//
// Fields:
// - slice: A slice of pointers to TaxNode[T] representing the taxon nodes.
// - taxonomy: A pointer to the Taxonomy[T] instance that these taxon nodes are part of.
// - slice: A slice of pointers to TaxNode representing the taxon nodes.
// - taxonomy: A pointer to the Taxonomy instance that these taxon nodes are part of.
type TaxonSlice struct {
slice []*TaxNode
taxonomy *Taxonomy
}
// NewTaxonSlice creates a new TaxonSlice with the specified size and capacity.
// It initializes the slice of TaxNode pointers and associates it with the given taxonomy.
//
// Parameters:
// - size: The initial size of the slice.
// - capacity: The capacity of the slice.
//
// Returns:
// - A pointer to the newly created TaxonSlice.
func (taxonomy *Taxonomy) NewTaxonSlice(size, capacity int) *TaxonSlice {
return &TaxonSlice{
slice: make([]*TaxNode, size, capacity),
@ -25,14 +44,14 @@ func (taxonomy *Taxonomy) NewTaxonSlice(size, capacity int) *TaxonSlice {
}
}
// Get retrieves the TaxNode[T] at the specified index from the TaxonSlice.
// Get retrieves the TaxNode at the specified index from the TaxonSlice.
// It returns the taxon node corresponding to the provided index.
//
// Parameters:
// - i: An integer representing the index of the taxon node to retrieve.
//
// Returns:
// - A pointer to the TaxNode[T] at the specified index in the slice.
// - A pointer to the TaxNode at the specified index in the slice.
func (slice *TaxonSlice) Get(i int) *TaxNode {
if slice == nil {
return nil
@ -40,7 +59,7 @@ func (slice *TaxonSlice) Get(i int) *TaxNode {
return slice.slice[i]
}
// Len returns the number of TaxNode[T] instances in the TaxonSlice.
// Len returns the number of TaxNode instances in the TaxonSlice.
// It provides the count of taxon nodes contained within the slice.
//
// Returns:
@ -81,6 +100,15 @@ func (path *TaxonSlice) String() string {
return buffer.String()
}
// Reverse reverses the order of the TaxonSlice.
// If inplace is true, the original slice is modified; otherwise, a new reversed
// TaxonSlice is returned.
//
// Parameters:
// - inplace: A boolean indicating whether to reverse the slice in place.
//
// Returns:
// - A pointer to the reversed TaxonSlice. If inplace is true, it returns the original slice.
func (slice *TaxonSlice) Reverse(inplace bool) *TaxonSlice {
if slice == nil {
return nil

View File

@ -77,6 +77,7 @@ func TaxonAsString(taxon *obitax.Taxon, pattern string) string {
}
func TaxonWriter(itaxa *obitax.ITaxon, pattern string) {
for itaxa.Next() {
fmt.Println(TaxonAsString(itaxa.Get(), pattern))
}