mirror of
https://github.com/metabarcoding/obitools4.git
synced 2026-03-25 13:30:52 +00:00
363 lines
8.5 KiB
Go
363 lines
8.5 KiB
Go
|
|
package obikmer
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"strconv"
|
||
|
|
|
||
|
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiutils"
|
||
|
|
)
|
||
|
|
|
||
|
|
// ==================================
|
||
|
|
// KMER SET ATTRIBUTE API
|
||
|
|
// Mimic BioSequence attribute API from obiseq/attributes.go
|
||
|
|
// ==================================
|
||
|
|
|
||
|
|
// HasAttribute vérifie si une clé d'attribut existe
|
||
|
|
func (ks *KmerSet) HasAttribute(key string) bool {
|
||
|
|
_, ok := ks.Metadata[key]
|
||
|
|
return ok
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetAttribute récupère la valeur d'un attribut
|
||
|
|
// Cas particuliers: "id" utilise Id(), "k" utilise K()
|
||
|
|
func (ks *KmerSet) GetAttribute(key string) (interface{}, bool) {
|
||
|
|
switch key {
|
||
|
|
case "id":
|
||
|
|
return ks.Id(), true
|
||
|
|
case "k":
|
||
|
|
return ks.K(), true
|
||
|
|
default:
|
||
|
|
value, ok := ks.Metadata[key]
|
||
|
|
return value, ok
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// SetAttribute définit la valeur d'un attribut
|
||
|
|
// Cas particuliers: "id" utilise SetId(), "k" est immutable (panique)
|
||
|
|
func (ks *KmerSet) SetAttribute(key string, value interface{}) {
|
||
|
|
switch key {
|
||
|
|
case "id":
|
||
|
|
if id, ok := value.(string); ok {
|
||
|
|
ks.SetId(id)
|
||
|
|
} else {
|
||
|
|
panic(fmt.Sprintf("id must be a string, got %T", value))
|
||
|
|
}
|
||
|
|
case "k":
|
||
|
|
panic("k is immutable and cannot be modified via SetAttribute")
|
||
|
|
default:
|
||
|
|
ks.Metadata[key] = value
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// DeleteAttribute supprime un attribut
|
||
|
|
func (ks *KmerSet) DeleteAttribute(key string) {
|
||
|
|
delete(ks.Metadata, key)
|
||
|
|
}
|
||
|
|
|
||
|
|
// RemoveAttribute supprime un attribut (alias de DeleteAttribute)
|
||
|
|
func (ks *KmerSet) RemoveAttribute(key string) {
|
||
|
|
ks.DeleteAttribute(key)
|
||
|
|
}
|
||
|
|
|
||
|
|
// RenameAttribute renomme un attribut
|
||
|
|
func (ks *KmerSet) RenameAttribute(newName, oldName string) {
|
||
|
|
if value, ok := ks.Metadata[oldName]; ok {
|
||
|
|
ks.Metadata[newName] = value
|
||
|
|
delete(ks.Metadata, oldName)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetIntAttribute récupère un attribut en tant qu'entier
|
||
|
|
func (ks *KmerSet) GetIntAttribute(key string) (int, bool) {
|
||
|
|
value, ok := ks.Metadata[key]
|
||
|
|
if !ok {
|
||
|
|
return 0, false
|
||
|
|
}
|
||
|
|
|
||
|
|
switch v := value.(type) {
|
||
|
|
case int:
|
||
|
|
return v, true
|
||
|
|
case int64:
|
||
|
|
return int(v), true
|
||
|
|
case float64:
|
||
|
|
return int(v), true
|
||
|
|
case string:
|
||
|
|
if i, err := strconv.Atoi(v); err == nil {
|
||
|
|
return i, true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0, false
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFloatAttribute récupère un attribut en tant que float64
|
||
|
|
func (ks *KmerSet) GetFloatAttribute(key string) (float64, bool) {
|
||
|
|
value, ok := ks.Metadata[key]
|
||
|
|
if !ok {
|
||
|
|
return 0, false
|
||
|
|
}
|
||
|
|
|
||
|
|
switch v := value.(type) {
|
||
|
|
case float64:
|
||
|
|
return v, true
|
||
|
|
case float32:
|
||
|
|
return float64(v), true
|
||
|
|
case int:
|
||
|
|
return float64(v), true
|
||
|
|
case int64:
|
||
|
|
return float64(v), true
|
||
|
|
case string:
|
||
|
|
if f, err := strconv.ParseFloat(v, 64); err == nil {
|
||
|
|
return f, true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0, false
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetNumericAttribute récupère un attribut numérique (alias de GetFloatAttribute)
|
||
|
|
func (ks *KmerSet) GetNumericAttribute(key string) (float64, bool) {
|
||
|
|
return ks.GetFloatAttribute(key)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetStringAttribute récupère un attribut en tant que chaîne
|
||
|
|
func (ks *KmerSet) GetStringAttribute(key string) (string, bool) {
|
||
|
|
value, ok := ks.Metadata[key]
|
||
|
|
if !ok {
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
|
||
|
|
switch v := value.(type) {
|
||
|
|
case string:
|
||
|
|
return v, true
|
||
|
|
default:
|
||
|
|
return fmt.Sprintf("%v", v), true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetBoolAttribute récupère un attribut en tant que booléen
|
||
|
|
func (ks *KmerSet) GetBoolAttribute(key string) (bool, bool) {
|
||
|
|
value, ok := ks.Metadata[key]
|
||
|
|
if !ok {
|
||
|
|
return false, false
|
||
|
|
}
|
||
|
|
|
||
|
|
switch v := value.(type) {
|
||
|
|
case bool:
|
||
|
|
return v, true
|
||
|
|
case int:
|
||
|
|
return v != 0, true
|
||
|
|
case string:
|
||
|
|
if b, err := strconv.ParseBool(v); err == nil {
|
||
|
|
return b, true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false, false
|
||
|
|
}
|
||
|
|
|
||
|
|
// AttributeKeys retourne l'ensemble des clés d'attributs
|
||
|
|
func (ks *KmerSet) AttributeKeys() obiutils.Set[string] {
|
||
|
|
keys := obiutils.MakeSet[string]()
|
||
|
|
for key := range ks.Metadata {
|
||
|
|
keys.Add(key)
|
||
|
|
}
|
||
|
|
return keys
|
||
|
|
}
|
||
|
|
|
||
|
|
// Keys retourne l'ensemble des clés d'attributs (alias de AttributeKeys)
|
||
|
|
func (ks *KmerSet) Keys() obiutils.Set[string] {
|
||
|
|
return ks.AttributeKeys()
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================
|
||
|
|
// KMER SET GROUP ATTRIBUTE API
|
||
|
|
// Métadonnées du groupe + accès via Get() pour les sets individuels
|
||
|
|
// ==================================
|
||
|
|
|
||
|
|
// HasAttribute vérifie si une clé d'attribut existe pour le groupe
|
||
|
|
func (ksg *KmerSetGroup) HasAttribute(key string) bool {
|
||
|
|
_, ok := ksg.Metadata[key]
|
||
|
|
return ok
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetAttribute récupère la valeur d'un attribut du groupe
|
||
|
|
// Cas particuliers: "id" utilise Id(), "k" utilise K()
|
||
|
|
func (ksg *KmerSetGroup) GetAttribute(key string) (interface{}, bool) {
|
||
|
|
switch key {
|
||
|
|
case "id":
|
||
|
|
return ksg.Id(), true
|
||
|
|
case "k":
|
||
|
|
return ksg.K(), true
|
||
|
|
default:
|
||
|
|
value, ok := ksg.Metadata[key]
|
||
|
|
return value, ok
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// SetAttribute définit la valeur d'un attribut du groupe
|
||
|
|
// Cas particuliers: "id" utilise SetId(), "k" est immutable (panique)
|
||
|
|
func (ksg *KmerSetGroup) SetAttribute(key string, value interface{}) {
|
||
|
|
switch key {
|
||
|
|
case "id":
|
||
|
|
if id, ok := value.(string); ok {
|
||
|
|
ksg.SetId(id)
|
||
|
|
} else {
|
||
|
|
panic(fmt.Sprintf("id must be a string, got %T", value))
|
||
|
|
}
|
||
|
|
case "k":
|
||
|
|
panic("k is immutable and cannot be modified via SetAttribute")
|
||
|
|
default:
|
||
|
|
ksg.Metadata[key] = value
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// DeleteAttribute supprime un attribut du groupe
|
||
|
|
func (ksg *KmerSetGroup) DeleteAttribute(key string) {
|
||
|
|
delete(ksg.Metadata, key)
|
||
|
|
}
|
||
|
|
|
||
|
|
// RemoveAttribute supprime un attribut du groupe (alias)
|
||
|
|
func (ksg *KmerSetGroup) RemoveAttribute(key string) {
|
||
|
|
ksg.DeleteAttribute(key)
|
||
|
|
}
|
||
|
|
|
||
|
|
// RenameAttribute renomme un attribut du groupe
|
||
|
|
func (ksg *KmerSetGroup) RenameAttribute(newName, oldName string) {
|
||
|
|
if value, ok := ksg.Metadata[oldName]; ok {
|
||
|
|
ksg.Metadata[newName] = value
|
||
|
|
delete(ksg.Metadata, oldName)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetIntAttribute récupère un attribut entier du groupe
|
||
|
|
func (ksg *KmerSetGroup) GetIntAttribute(key string) (int, bool) {
|
||
|
|
value, ok := ksg.GetAttribute(key)
|
||
|
|
if !ok {
|
||
|
|
return 0, false
|
||
|
|
}
|
||
|
|
|
||
|
|
switch v := value.(type) {
|
||
|
|
case int:
|
||
|
|
return v, true
|
||
|
|
case int64:
|
||
|
|
return int(v), true
|
||
|
|
case float64:
|
||
|
|
return int(v), true
|
||
|
|
case string:
|
||
|
|
if i, err := strconv.Atoi(v); err == nil {
|
||
|
|
return i, true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0, false
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFloatAttribute récupère un attribut float64 du groupe
|
||
|
|
func (ksg *KmerSetGroup) GetFloatAttribute(key string) (float64, bool) {
|
||
|
|
value, ok := ksg.GetAttribute(key)
|
||
|
|
if !ok {
|
||
|
|
return 0, false
|
||
|
|
}
|
||
|
|
|
||
|
|
switch v := value.(type) {
|
||
|
|
case float64:
|
||
|
|
return v, true
|
||
|
|
case float32:
|
||
|
|
return float64(v), true
|
||
|
|
case int:
|
||
|
|
return float64(v), true
|
||
|
|
case int64:
|
||
|
|
return float64(v), true
|
||
|
|
case string:
|
||
|
|
if f, err := strconv.ParseFloat(v, 64); err == nil {
|
||
|
|
return f, true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0, false
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetNumericAttribute récupère un attribut numérique du groupe
|
||
|
|
func (ksg *KmerSetGroup) GetNumericAttribute(key string) (float64, bool) {
|
||
|
|
return ksg.GetFloatAttribute(key)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetStringAttribute récupère un attribut chaîne du groupe
|
||
|
|
func (ksg *KmerSetGroup) GetStringAttribute(key string) (string, bool) {
|
||
|
|
value, ok := ksg.GetAttribute(key)
|
||
|
|
if !ok {
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
|
||
|
|
switch v := value.(type) {
|
||
|
|
case string:
|
||
|
|
return v, true
|
||
|
|
default:
|
||
|
|
return fmt.Sprintf("%v", v), true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetBoolAttribute récupère un attribut booléen du groupe
|
||
|
|
func (ksg *KmerSetGroup) GetBoolAttribute(key string) (bool, bool) {
|
||
|
|
value, ok := ksg.GetAttribute(key)
|
||
|
|
if !ok {
|
||
|
|
return false, false
|
||
|
|
}
|
||
|
|
|
||
|
|
switch v := value.(type) {
|
||
|
|
case bool:
|
||
|
|
return v, true
|
||
|
|
case int:
|
||
|
|
return v != 0, true
|
||
|
|
case string:
|
||
|
|
if b, err := strconv.ParseBool(v); err == nil {
|
||
|
|
return b, true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false, false
|
||
|
|
}
|
||
|
|
|
||
|
|
// AttributeKeys retourne l'ensemble des clés d'attributs du groupe
|
||
|
|
func (ksg *KmerSetGroup) AttributeKeys() obiutils.Set[string] {
|
||
|
|
keys := obiutils.MakeSet[string]()
|
||
|
|
for key := range ksg.Metadata {
|
||
|
|
keys.Add(key)
|
||
|
|
}
|
||
|
|
return keys
|
||
|
|
}
|
||
|
|
|
||
|
|
// Keys retourne l'ensemble des clés d'attributs du groupe (alias)
|
||
|
|
func (ksg *KmerSetGroup) Keys() obiutils.Set[string] {
|
||
|
|
return ksg.AttributeKeys()
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================
|
||
|
|
// MÉTHODES POUR ACCÉDER AUX ATTRIBUTS DES SETS INDIVIDUELS VIA Get()
|
||
|
|
// Architecture zero-copy: ksg.Get(i).SetAttribute(...)
|
||
|
|
// ==================================
|
||
|
|
|
||
|
|
// Exemple d'utilisation:
|
||
|
|
// Pour accéder aux métadonnées d'un KmerSet individuel dans un groupe:
|
||
|
|
// ks := ksg.Get(0)
|
||
|
|
// ks.SetAttribute("level", 1)
|
||
|
|
// hasLevel := ks.HasAttribute("level")
|
||
|
|
//
|
||
|
|
// Pour les métadonnées du groupe:
|
||
|
|
// ksg.SetAttribute("name", "FrequencyFilter")
|
||
|
|
// name, ok := ksg.GetStringAttribute("name")
|
||
|
|
|
||
|
|
// AllAttributeKeys retourne toutes les clés d'attributs uniques du groupe ET de tous ses sets
|
||
|
|
func (ksg *KmerSetGroup) AllAttributeKeys() obiutils.Set[string] {
|
||
|
|
keys := obiutils.MakeSet[string]()
|
||
|
|
|
||
|
|
// Ajouter les clés du groupe
|
||
|
|
for key := range ksg.Metadata {
|
||
|
|
keys.Add(key)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Ajouter les clés de chaque set
|
||
|
|
for _, ks := range ksg.sets {
|
||
|
|
for key := range ks.Metadata {
|
||
|
|
keys.Add(key)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return keys
|
||
|
|
}
|