From afcb43b352527587018936f78b96a573bcfc34ea Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Thu, 5 Feb 2026 15:02:27 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20la=20gestion=20des=20m=C3=A9tadonn?= =?UTF-8?q?=C3=A9es=20utilisateur=20dans=20KmerSet=20et=20KmerSetGroup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- pkg/obikmer/kmer_set.go | 26 ++++++++++++------ pkg/obikmer/kmer_set_group.go | 26 +++++++++++++----- pkg/obikmer/kmer_set_persistence.go | 42 ++++++++++++++++++++--------- pkg/obioptions/version.go | 2 +- 4 files changed, 69 insertions(+), 27 deletions(-) diff --git a/pkg/obikmer/kmer_set.go b/pkg/obikmer/kmer_set.go index c0e69d1..0eec9df 100644 --- a/pkg/obikmer/kmer_set.go +++ b/pkg/obikmer/kmer_set.go @@ -10,23 +10,26 @@ import ( // 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 type KmerSet struct { - K int // Taille des k-mers - bitmap *roaring64.Bitmap // Bitmap contenant les k-mers + K int // Taille des 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 func NewKmerSet(k int) *KmerSet { return &KmerSet{ - K: k, - bitmap: roaring64.New(), + K: k, + bitmap: roaring64.New(), + Metadata: make(map[string]interface{}), } } // NewKmerSetFromBitmap crée un KmerSet à partir d'un bitmap existant func NewKmerSetFromBitmap(k int, bitmap *roaring64.Bitmap) *KmerSet { return &KmerSet{ - K: k, - bitmap: bitmap, + K: k, + bitmap: bitmap, + Metadata: make(map[string]interface{}), } } @@ -73,9 +76,16 @@ func (ks *KmerSet) Clear() { // Clone crée une copie de l'ensemble 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{ - K: ks.K, - bitmap: ks.bitmap.Clone(), + K: ks.K, + bitmap: ks.bitmap.Clone(), + Metadata: metadata, } } diff --git a/pkg/obikmer/kmer_set_group.go b/pkg/obikmer/kmer_set_group.go index 00dbf99..6bbf39e 100644 --- a/pkg/obikmer/kmer_set_group.go +++ b/pkg/obikmer/kmer_set_group.go @@ -9,8 +9,9 @@ import ( // KmerSetGroup représente un vecteur de KmerSet // Utilisé pour gérer plusieurs ensembles de k-mers (par exemple, par niveau de fréquence) type KmerSetGroup struct { - K int // Taille des k-mers - sets []*KmerSet // Vecteur de KmerSet + K int // Taille des k-mers + 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 @@ -20,13 +21,16 @@ func NewKmerSetGroup(k int, n int) *KmerSetGroup { } sets := make([]*KmerSet, n) + metadata := make([]map[string]interface{}, n) for i := range sets { sets[i] = NewKmerSet(k) + metadata[i] = make(map[string]interface{}) } return &KmerSetGroup{ - K: k, - sets: sets, + K: k, + sets: sets, + Metadata: metadata, } } @@ -92,12 +96,22 @@ func (ksg *KmerSetGroup) Clear() { // Clone crée une copie complète du groupe func (ksg *KmerSetGroup) Clone() *KmerSetGroup { clonedSets := make([]*KmerSet, len(ksg.sets)) + clonedMetadata := make([]map[string]interface{}, len(ksg.Metadata)) + for i, ks := range ksg.sets { 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{ - K: ksg.K, - sets: clonedSets, + K: ksg.K, + sets: clonedSets, + Metadata: clonedMetadata, } } diff --git a/pkg/obikmer/kmer_set_persistence.go b/pkg/obikmer/kmer_set_persistence.go index 8339cb6..531d59f 100644 --- a/pkg/obikmer/kmer_set_persistence.go +++ b/pkg/obikmer/kmer_set_persistence.go @@ -36,10 +36,12 @@ func (f MetadataFormat) String() string { // KmerSetMetadata contient les métadonnées d'un KmerSet ou KmerSetGroup type KmerSetMetadata struct { - K int `toml:"k" yaml:"k" json:"k"` // Taille des k-mers - 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 - Files []string `toml:"files" yaml:"files" json:"files"` // Liste des fichiers .roaring + K int `toml:"k" yaml:"k" json:"k"` // Taille des k-mers + 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 + 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 @@ -52,10 +54,11 @@ func (ks *KmerSet) Save(directory string, format MetadataFormat) error { // Métadonnées metadata := KmerSetMetadata{ - K: ks.K, - Type: "KmerSet", - Size: 1, - Files: []string{"set_0.roaring"}, + K: ks.K, + Type: "KmerSet", + Size: 1, + Files: []string{"set_0.roaring"}, + UserMetadata: ks.Metadata, // Sauvegarder les métadonnées utilisateur } // Sauvegarder les métadonnées @@ -105,6 +108,12 @@ func LoadKmerSet(directory string) (*KmerSet, error) { defer file.Close() 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 { 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{ - K: ksg.K, - Type: "KmerSetGroup", - Size: len(ksg.sets), - Files: files, + K: ksg.K, + Type: "KmerSetGroup", + Size: len(ksg.sets), + Files: files, + SetsMetadata: ksg.Metadata, // Sauvegarder les métadonnées de chaque set } // Sauvegarder les métadonnées @@ -177,6 +187,14 @@ func LoadKmerSetGroup(directory string) (*KmerSetGroup, error) { // Créer le groupe 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 for i, filename := range metadata.Files { bitmapPath := filepath.Join(directory, filename) diff --git a/pkg/obioptions/version.go b/pkg/obioptions/version.go index e01e0da..adccd28 100644 --- a/pkg/obioptions/version.go +++ b/pkg/obioptions/version.go @@ -8,7 +8,7 @@ import ( // corresponds to the last commit, and not the one when the file will be // commited -var _Commit = "aa468ec" +var _Commit = "b26b76c" var _Version = "Release 4.4.0" // Version returns the version of the obitools package.