Files
obitools4/pkg/obitax/taxonomy.go

162 lines
3.1 KiB
Go
Raw Normal View History

2022-01-13 23:27:39 +01:00
package obitax
import (
"fmt"
"regexp"
"strconv"
2022-01-13 23:27:39 +01:00
)
type TaxName struct {
name *string
nameclass *string
}
type Taxonomy struct {
nodes *TaxonSet
alias map[int]*TaxNode
index map[string]*TaxonSet
}
func NewTaxonomy() *Taxonomy {
set := make(TaxonSet)
taxonomy := Taxonomy{
nodes: &set,
alias: make(TaxonSet),
index: make(map[string]*TaxonSet)}
return &taxonomy
}
func (taxonomy *Taxonomy) TaxonSet() *TaxonSet {
return taxonomy.nodes
}
func (taxonomy *Taxonomy) Alias() *map[int]*TaxNode {
return &(taxonomy.alias)
}
func (taxonomy *Taxonomy) Index() *map[string]*TaxonSet {
return &(taxonomy.index)
}
func (taxonomy *Taxonomy) Len() int {
2022-01-13 23:27:39 +01:00
return len(*taxonomy.nodes)
}
func (taxonomy *Taxonomy) AddNewTaxa(taxid, parent int, rank string, replace bool, init bool) (*TaxNode, error) {
if !replace {
_, ok := (*taxonomy.nodes)[taxid]
if ok {
2022-01-14 16:10:19 +01:00
return nil, fmt.Errorf("trying to add taxoon %d already present in the taxonomy", taxid)
2022-01-13 23:27:39 +01:00
}
}
n := NewTaxNode(taxid, parent, rank)
(*taxonomy.nodes)[taxid] = n
return n, nil
}
// func (taxonomy *Taxonomy) Taxon(taxid int) (*TaxNode, error) {
// t, ok := (*taxonomy.nodes)[taxid]
// if !ok {
// a, aok := taxonomy.alias[taxid]
// if !aok {
// return nil, fmt.Errorf("Taxid %d is not part of the taxonomy", taxid)
// }
// t = a
// }
// return t, nil
// }
func (taxonomy *Taxonomy) Taxon(taxid interface{}) (*TaxNode, error) {
var itaxid int
var err error
switch v := taxid.(type) {
case int:
itaxid = v
case string:
itaxid, err = strconv.Atoi(v)
if err != nil {
re := regexp.MustCompile(`TX:(\d+)`)
parts := re.FindStringSubmatch(v)
if len(parts) != 2 {
return nil, fmt.Errorf("I cannot parse taxid from %s", v)
}
itaxid, _ = strconv.Atoi(parts[1])
}
}
t, ok := (*taxonomy.nodes)[itaxid]
2022-01-13 23:27:39 +01:00
if !ok {
a, aok := taxonomy.alias[itaxid]
2022-01-13 23:27:39 +01:00
if !aok {
2022-01-14 16:10:19 +01:00
return nil, fmt.Errorf("Taxid %d is not part of the taxonomy", taxid)
2022-01-13 23:27:39 +01:00
}
t = a
}
return t, nil
}
func (taxonomy *Taxonomy) AddNewName(taxid int, name, nameclass *string) error {
node, node_err := taxonomy.Taxon(taxid)
if node_err != nil {
return node_err
}
if *nameclass == "scientific name" {
node.scientificname = name
} else {
names := node.alternatenames
if names == nil {
n := make(map[string]*string)
names = &n
node.alternatenames = names
} else {
(*names)[*name] = nameclass
}
}
i, ok := taxonomy.index[*name]
if !ok {
tnm := make(TaxonSet)
i = &tnm
taxonomy.index[*name] = i
}
(*i)[taxid] = node
return nil
}
func (taxonomy *Taxonomy) ReindexParent() error {
var ok bool
for _, taxon := range *taxonomy.nodes {
taxon.pparent, ok = (*taxonomy.nodes)[taxon.parent]
if !ok {
2022-01-14 16:10:19 +01:00
return fmt.Errorf("Parent %d of taxon %d is not defined in taxonomy",
2022-01-13 23:27:39 +01:00
taxon.taxid,
2022-01-14 16:10:19 +01:00
taxon.parent)
2022-01-13 23:27:39 +01:00
}
}
return nil
}
func MakeTaxName(name, nameclass *string) *TaxName {
tn := TaxName{name, nameclass}
return &tn
}
func (taxonomy *Taxonomy) AddNewAlias(newtaxid, oldtaxid int) error {
n, node_err := taxonomy.Taxon(newtaxid)
if node_err != nil {
return node_err
}
taxonomy.alias[oldtaxid] = n
return nil
}