Ajout de la gestion des métadonnées utilisateur dans KmerSet et KmerSetGroup

Cette modification ajoute la capacité de stocker et de persister des métadonnées utilisateur dans les structures KmerSet et KmerSetGroup. Les changements incluent l'ajout d'un champ Metadata dans KmerSet et KmerSetGroup, ainsi que la mise à jour des méthodes de clonage et de persistance pour gérer ces métadonnées. Cela permet de conserver des informations supplémentaires liées aux ensembles de k-mers tout en maintenant la compatibilité avec les opérations existantes.
This commit is contained in:
Eric Coissac
2026-02-05 15:02:27 +01:00
parent b26b76cbf8
commit afcb43b352
4 changed files with 69 additions and 27 deletions

View File

@@ -10,23 +10,26 @@ import (
// KmerSet encapsule un ensemble de k-mers stockés dans un Roaring Bitmap // KmerSet encapsule un ensemble de k-mers stockés dans un Roaring Bitmap
// Fournit des méthodes utilitaires pour manipuler des ensembles de k-mers // Fournit des méthodes utilitaires pour manipuler des ensembles de k-mers
type KmerSet struct { type KmerSet struct {
K int // Taille des k-mers K int // Taille des k-mers
bitmap *roaring64.Bitmap // Bitmap contenant les k-mers bitmap *roaring64.Bitmap // Bitmap contenant les k-mers
Metadata map[string]interface{} // Métadonnées utilisateur (clé=valeur atomique)
} }
// NewKmerSet crée un nouveau KmerSet vide // NewKmerSet crée un nouveau KmerSet vide
func NewKmerSet(k int) *KmerSet { func NewKmerSet(k int) *KmerSet {
return &KmerSet{ return &KmerSet{
K: k, K: k,
bitmap: roaring64.New(), bitmap: roaring64.New(),
Metadata: make(map[string]interface{}),
} }
} }
// NewKmerSetFromBitmap crée un KmerSet à partir d'un bitmap existant // NewKmerSetFromBitmap crée un KmerSet à partir d'un bitmap existant
func NewKmerSetFromBitmap(k int, bitmap *roaring64.Bitmap) *KmerSet { func NewKmerSetFromBitmap(k int, bitmap *roaring64.Bitmap) *KmerSet {
return &KmerSet{ return &KmerSet{
K: k, K: k,
bitmap: bitmap, bitmap: bitmap,
Metadata: make(map[string]interface{}),
} }
} }
@@ -73,9 +76,16 @@ func (ks *KmerSet) Clear() {
// Clone crée une copie de l'ensemble // Clone crée une copie de l'ensemble
func (ks *KmerSet) Clone() *KmerSet { func (ks *KmerSet) Clone() *KmerSet {
// Copier les métadonnées
metadata := make(map[string]interface{}, len(ks.Metadata))
for k, v := range ks.Metadata {
metadata[k] = v
}
return &KmerSet{ return &KmerSet{
K: ks.K, K: ks.K,
bitmap: ks.bitmap.Clone(), bitmap: ks.bitmap.Clone(),
Metadata: metadata,
} }
} }

View File

@@ -9,8 +9,9 @@ import (
// KmerSetGroup représente un vecteur de KmerSet // KmerSetGroup représente un vecteur de KmerSet
// Utilisé pour gérer plusieurs ensembles de k-mers (par exemple, par niveau de fréquence) // Utilisé pour gérer plusieurs ensembles de k-mers (par exemple, par niveau de fréquence)
type KmerSetGroup struct { type KmerSetGroup struct {
K int // Taille des k-mers K int // Taille des k-mers
sets []*KmerSet // Vecteur de KmerSet sets []*KmerSet // Vecteur de KmerSet
Metadata []map[string]interface{} // Métadonnées par KmerSet (même longueur que sets)
} }
// NewKmerSetGroup crée un nouveau groupe de n KmerSets // NewKmerSetGroup crée un nouveau groupe de n KmerSets
@@ -20,13 +21,16 @@ func NewKmerSetGroup(k int, n int) *KmerSetGroup {
} }
sets := make([]*KmerSet, n) sets := make([]*KmerSet, n)
metadata := make([]map[string]interface{}, n)
for i := range sets { for i := range sets {
sets[i] = NewKmerSet(k) sets[i] = NewKmerSet(k)
metadata[i] = make(map[string]interface{})
} }
return &KmerSetGroup{ return &KmerSetGroup{
K: k, K: k,
sets: sets, sets: sets,
Metadata: metadata,
} }
} }
@@ -92,12 +96,22 @@ func (ksg *KmerSetGroup) Clear() {
// Clone crée une copie complète du groupe // Clone crée une copie complète du groupe
func (ksg *KmerSetGroup) Clone() *KmerSetGroup { func (ksg *KmerSetGroup) Clone() *KmerSetGroup {
clonedSets := make([]*KmerSet, len(ksg.sets)) clonedSets := make([]*KmerSet, len(ksg.sets))
clonedMetadata := make([]map[string]interface{}, len(ksg.Metadata))
for i, ks := range ksg.sets { for i, ks := range ksg.sets {
clonedSets[i] = ks.Clone() clonedSets[i] = ks.Clone()
// Copier les métadonnées du groupe
clonedMetadata[i] = make(map[string]interface{}, len(ksg.Metadata[i]))
for k, v := range ksg.Metadata[i] {
clonedMetadata[i][k] = v
}
} }
return &KmerSetGroup{ return &KmerSetGroup{
K: ksg.K, K: ksg.K,
sets: clonedSets, sets: clonedSets,
Metadata: clonedMetadata,
} }
} }

View File

@@ -36,10 +36,12 @@ func (f MetadataFormat) String() string {
// KmerSetMetadata contient les métadonnées d'un KmerSet ou KmerSetGroup // KmerSetMetadata contient les métadonnées d'un KmerSet ou KmerSetGroup
type KmerSetMetadata struct { type KmerSetMetadata struct {
K int `toml:"k" yaml:"k" json:"k"` // Taille des k-mers K int `toml:"k" yaml:"k" json:"k"` // Taille des k-mers
Type string `toml:"type" yaml:"type" json:"type"` // "KmerSet" ou "KmerSetGroup" Type string `toml:"type" yaml:"type" json:"type"` // "KmerSet" ou "KmerSetGroup"
Size int `toml:"size" yaml:"size" json:"size"` // 1 pour KmerSet, n pour KmerSetGroup Size int `toml:"size" yaml:"size" json:"size"` // 1 pour KmerSet, n pour KmerSetGroup
Files []string `toml:"files" yaml:"files" json:"files"` // Liste des fichiers .roaring Files []string `toml:"files" yaml:"files" json:"files"` // Liste des fichiers .roaring
UserMetadata map[string]interface{} `toml:"user_metadata,omitempty" yaml:"user_metadata,omitempty" json:"user_metadata,omitempty"` // Métadonnées KmerSet unique
SetsMetadata []map[string]interface{} `toml:"sets_metadata,omitempty" yaml:"sets_metadata,omitempty" json:"sets_metadata,omitempty"` // Métadonnées par set (KmerSetGroup)
} }
// SaveKmerSet sauvegarde un KmerSet dans un répertoire // SaveKmerSet sauvegarde un KmerSet dans un répertoire
@@ -52,10 +54,11 @@ func (ks *KmerSet) Save(directory string, format MetadataFormat) error {
// Métadonnées // Métadonnées
metadata := KmerSetMetadata{ metadata := KmerSetMetadata{
K: ks.K, K: ks.K,
Type: "KmerSet", Type: "KmerSet",
Size: 1, Size: 1,
Files: []string{"set_0.roaring"}, Files: []string{"set_0.roaring"},
UserMetadata: ks.Metadata, // Sauvegarder les métadonnées utilisateur
} }
// Sauvegarder les métadonnées // Sauvegarder les métadonnées
@@ -105,6 +108,12 @@ func LoadKmerSet(directory string) (*KmerSet, error) {
defer file.Close() defer file.Close()
ks := NewKmerSet(metadata.K) ks := NewKmerSet(metadata.K)
// Charger les métadonnées utilisateur
if metadata.UserMetadata != nil {
ks.Metadata = metadata.UserMetadata
}
if _, err := ks.bitmap.ReadFrom(file); err != nil { if _, err := ks.bitmap.ReadFrom(file); err != nil {
return nil, fmt.Errorf("failed to read bitmap: %w", err) return nil, fmt.Errorf("failed to read bitmap: %w", err)
} }
@@ -127,10 +136,11 @@ func (ksg *KmerSetGroup) Save(directory string, format MetadataFormat) error {
} }
metadata := KmerSetMetadata{ metadata := KmerSetMetadata{
K: ksg.K, K: ksg.K,
Type: "KmerSetGroup", Type: "KmerSetGroup",
Size: len(ksg.sets), Size: len(ksg.sets),
Files: files, Files: files,
SetsMetadata: ksg.Metadata, // Sauvegarder les métadonnées de chaque set
} }
// Sauvegarder les métadonnées // Sauvegarder les métadonnées
@@ -177,6 +187,14 @@ func LoadKmerSetGroup(directory string) (*KmerSetGroup, error) {
// Créer le groupe // Créer le groupe
ksg := NewKmerSetGroup(metadata.K, metadata.Size) ksg := NewKmerSetGroup(metadata.K, metadata.Size)
// Charger les métadonnées de chaque set
if metadata.SetsMetadata != nil {
if len(metadata.SetsMetadata) != metadata.Size {
return nil, fmt.Errorf("metadata size mismatch: expected %d, got %d", metadata.Size, len(metadata.SetsMetadata))
}
ksg.Metadata = metadata.SetsMetadata
}
// Charger chaque bitmap // Charger chaque bitmap
for i, filename := range metadata.Files { for i, filename := range metadata.Files {
bitmapPath := filepath.Join(directory, filename) bitmapPath := filepath.Join(directory, filename)

View File

@@ -8,7 +8,7 @@ import (
// corresponds to the last commit, and not the one when the file will be // corresponds to the last commit, and not the one when the file will be
// commited // commited
var _Commit = "aa468ec" var _Commit = "b26b76c"
var _Version = "Release 4.4.0" var _Version = "Release 4.4.0"
// Version returns the version of the obitools package. // Version returns the version of the obitools package.