mirror of
https://github.com/metabarcoding/obitools4.git
synced 2025-06-29 16:20:46 +00:00
229 lines
4.4 KiB
Go
229 lines
4.4 KiB
Go
package obitax
|
|
|
|
import (
|
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiutils"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// 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 // 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,
|
|
}
|
|
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()
|
|
|
|
go func() {
|
|
for _, t := range set.set {
|
|
taxon := &Taxon{
|
|
Taxonomy: set.taxonomy,
|
|
Metadata: nil,
|
|
Node: t,
|
|
}
|
|
i.Push(taxon)
|
|
}
|
|
close(i.source)
|
|
}()
|
|
|
|
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()
|
|
|
|
go func() {
|
|
for _, t := range set.slice {
|
|
i.Push(&Taxon{
|
|
Taxonomy: set.taxonomy,
|
|
Node: t,
|
|
})
|
|
}
|
|
i.Close()
|
|
}()
|
|
|
|
return i
|
|
}
|
|
|
|
func (iterator *ITaxon) Push(taxon *Taxon) {
|
|
iterator.source <- taxon
|
|
}
|
|
|
|
func (iterator *ITaxon) Close() {
|
|
close(iterator.source)
|
|
}
|
|
|
|
// 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
|
|
}
|
|
next, ok := (<-iterator.source)
|
|
|
|
if ok {
|
|
iterator.current = next
|
|
return true
|
|
}
|
|
|
|
iterator.current = nil
|
|
*iterator.p_finished = true
|
|
return false
|
|
}
|
|
|
|
// 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 {
|
|
if iterator == nil {
|
|
return nil
|
|
}
|
|
|
|
return iterator.current
|
|
}
|
|
|
|
// Finished returns true if no more data is available from the iterator.
|
|
func (iterator *ITaxon) Finished() bool {
|
|
if iterator == nil {
|
|
return true
|
|
}
|
|
|
|
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 {
|
|
if iterator == nil {
|
|
return nil
|
|
}
|
|
return &ITaxon{
|
|
source: iterator.source,
|
|
current: nil,
|
|
finished: false,
|
|
p_finished: iterator.p_finished,
|
|
}
|
|
}
|
|
|
|
func (iterator *ITaxon) AddMetadata(name string, value interface{}) *ITaxon {
|
|
if iterator == nil {
|
|
return nil
|
|
}
|
|
|
|
i := NewITaxon()
|
|
|
|
go func() {
|
|
for iterator.Next() {
|
|
taxon := iterator.Get()
|
|
taxon.SetMetadata(name, value)
|
|
i.Push(taxon)
|
|
}
|
|
i.Close()
|
|
}()
|
|
|
|
return i
|
|
}
|
|
|
|
func (iterator *ITaxon) Concat(iterators ...*ITaxon) *ITaxon {
|
|
|
|
newIter := NewITaxon()
|
|
|
|
go func() {
|
|
if iterator != nil {
|
|
for iterator.Next() {
|
|
taxon := iterator.Get()
|
|
newIter.Push(taxon)
|
|
}
|
|
}
|
|
|
|
for _, iter := range iterators {
|
|
if iter != nil {
|
|
for iter.Next() {
|
|
taxon := iter.Get()
|
|
newIter.Push(taxon)
|
|
}
|
|
}
|
|
}
|
|
|
|
newIter.Close()
|
|
}()
|
|
|
|
return newIter
|
|
}
|
|
|
|
func (taxon *Taxon) ISubTaxonomy() *ITaxon {
|
|
|
|
taxo := taxon.Taxonomy
|
|
|
|
path := taxon.Path()
|
|
lpath := path.Len()
|
|
|
|
iter := NewITaxon()
|
|
|
|
parents := map[*TaxNode]bool{taxon.Node: true}
|
|
|
|
obiutils.RegisterAPipe()
|
|
|
|
go func() {
|
|
for i := lpath - 1; i >= 0; i-- {
|
|
taxon := path.Taxon(i)
|
|
iter.Push(taxon)
|
|
}
|
|
|
|
pushed := true
|
|
|
|
log.Warn(parents)
|
|
for pushed {
|
|
itaxo := taxo.Iterator()
|
|
pushed = false
|
|
for itaxo.Next() {
|
|
taxon := itaxo.Get()
|
|
|
|
if !parents[taxon.Node] && parents[taxon.Parent().Node] {
|
|
parents[taxon.Node] = true
|
|
iter.Push(taxon)
|
|
pushed = true
|
|
}
|
|
}
|
|
}
|
|
|
|
iter.Close()
|
|
obiutils.UnregisterPipe()
|
|
}()
|
|
|
|
return iter
|
|
}
|
|
|
|
func (taxonomy *Taxonomy) ISubTaxonomy(taxid string) *ITaxon {
|
|
taxon := taxonomy.Taxon(taxid)
|
|
|
|
if taxon == nil {
|
|
return nil
|
|
}
|
|
|
|
return taxon.ISubTaxonomy()
|
|
}
|