docs: translate comments to English

This commit translates all French comments in the kmer filtering and set management code to English, improving code readability and maintainability for international collaborators.
This commit is contained in:
Eric Coissac
2026-02-05 16:35:38 +01:00
parent 12ca62b06a
commit a43e6258be
5 changed files with 122 additions and 122 deletions

View File

@@ -6,26 +6,26 @@ import (
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq" "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
) )
// FrequencyFilter filtre les k-mers par fréquence minimale // FrequencyFilter filters k-mers by minimum frequency
// Spécialisation de KmerSetGroup index[i] contient les k-mers vus au moins i+1 fois // Specialization of KmerSetGroup where index[i] contains k-mers seen at least i+1 times
type FrequencyFilter struct { type FrequencyFilter struct {
*KmerSetGroup // Groupe de KmerSet (un par niveau de fréquence) *KmerSetGroup // Group of KmerSet (one per frequency level)
MinFreq int // v - fréquence minimale requise MinFreq int // v - minimum required frequency
} }
// NewFrequencyFilter crée un nouveau filtre par fréquence // NewFrequencyFilter creates a new frequency filter
// minFreq: nombre minimum d'occurrences requises (v) // minFreq: minimum number d'occurrences required (v)
func NewFrequencyFilter(k, minFreq int) *FrequencyFilter { func NewFrequencyFilter(k, minFreq int) *FrequencyFilter {
ff := &FrequencyFilter{ ff := &FrequencyFilter{
KmerSetGroup: NewKmerSetGroup(k, minFreq), KmerSetGroup: NewKmerSetGroup(k, minFreq),
MinFreq: minFreq, MinFreq: minFreq,
} }
// Initialiser les métadonnées de groupe // Initialize group metadata
ff.SetAttribute("type", "FrequencyFilter") ff.SetAttribute("type", "FrequencyFilter")
ff.SetAttribute("min_freq", minFreq) ff.SetAttribute("min_freq", minFreq)
// Initialiser les métadonnées de chaque niveau // Initialize metadata for each level
for i := 0; i < minFreq; i++ { for i := 0; i < minFreq; i++ {
level := ff.Get(i) level := ff.Get(i)
level.SetAttribute("level", i) level.SetAttribute("level", i)
@@ -36,8 +36,8 @@ func NewFrequencyFilter(k, minFreq int) *FrequencyFilter {
return ff return ff
} }
// AddSequence ajoute tous les k-mers d'une séquence au filtre // AddSequence adds all k-mers from a sequence to the filter
// Utilise un itérateur pour éviter l'allocation d'un vecteur intermédiaire // Uses an iterator to avoid allocating an intermediate vector
func (ff *FrequencyFilter) AddSequence(seq *obiseq.BioSequence) { func (ff *FrequencyFilter) AddSequence(seq *obiseq.BioSequence) {
rawSeq := seq.Sequence() rawSeq := seq.Sequence()
for canonical := range IterCanonicalKmers(rawSeq, ff.K()) { for canonical := range IterCanonicalKmers(rawSeq, ff.K()) {
@@ -45,49 +45,49 @@ func (ff *FrequencyFilter) AddSequence(seq *obiseq.BioSequence) {
} }
} }
// AddKmerCode ajoute un k-mer encodé au filtre (algorithme principal) // AddKmerCode adds an encoded k-mer to the filter (main algorithm)
func (ff *FrequencyFilter) AddKmerCode(kmer uint64) { func (ff *FrequencyFilter) AddKmerCode(kmer uint64) {
// Trouver le niveau actuel du k-mer // Find the current level of the k-mer
c := 0 c := 0
for c < ff.MinFreq && ff.Get(c).Contains(kmer) { for c < ff.MinFreq && ff.Get(c).Contains(kmer) {
c++ c++
} }
// Ajouter au niveau suivant (si pas encore au maximum) // Add to next level (if not yet at maximum)
if c < ff.MinFreq { if c < ff.MinFreq {
ff.Get(c).AddKmerCode(kmer) ff.Get(c).AddKmerCode(kmer)
} }
} }
// AddCanonicalKmerCode ajoute un k-mer encodé canonique au filtre // AddCanonicalKmerCode adds an encoded canonical k-mer to the filter
func (ff *FrequencyFilter) AddCanonicalKmerCode(kmer uint64) { func (ff *FrequencyFilter) AddCanonicalKmerCode(kmer uint64) {
canonical := CanonicalKmer(kmer, ff.K()) canonical := CanonicalKmer(kmer, ff.K())
ff.AddKmerCode(canonical) ff.AddKmerCode(canonical)
} }
// AddKmer ajoute un k-mer au filtre en encodant la séquence // AddKmer adds a k-mer to the filter by encoding the sequence
// La séquence doit avoir exactement k nucléotides // The sequence must have exactly k nucleotides
// Zero-allocation: encode directement sans créer de slice intermédiaire // Zero-allocation: encodes directly without creating an intermediate slice
func (ff *FrequencyFilter) AddKmer(seq []byte) { func (ff *FrequencyFilter) AddKmer(seq []byte) {
kmer := EncodeKmer(seq, ff.K()) kmer := EncodeKmer(seq, ff.K())
ff.AddKmerCode(kmer) ff.AddKmerCode(kmer)
} }
// AddCanonicalKmer ajoute un k-mer canonique au filtre en encodant la séquence // AddCanonicalKmer adds a canonical k-mer to the filter by encoding the sequence
// La séquence doit avoir exactement k nucléotides // The sequence must have exactly k nucleotides
// Zero-allocation: encode directement en forme canonique sans créer de slice intermédiaire // Zero-allocation: encodes directly in canonical form without creating an intermediate slice
func (ff *FrequencyFilter) AddCanonicalKmer(seq []byte) { func (ff *FrequencyFilter) AddCanonicalKmer(seq []byte) {
canonical := EncodeCanonicalKmer(seq, ff.K()) canonical := EncodeCanonicalKmer(seq, ff.K())
ff.AddKmerCode(canonical) ff.AddKmerCode(canonical)
} }
// GetFilteredSet retourne un KmerSet des k-mers avec fréquence ≥ minFreq // GetFilteredSet returns a KmerSet of k-mers with frequency ≥ minFreq
func (ff *FrequencyFilter) GetFilteredSet() *KmerSet { func (ff *FrequencyFilter) GetFilteredSet() *KmerSet {
// Les k-mers filtrés sont dans le dernier niveau // Filtered k-mers are in the last level
return ff.Get(ff.MinFreq - 1).Copy() return ff.Get(ff.MinFreq - 1).Copy()
} }
// GetKmersAtLevel retourne un KmerSet des k-mers vus au moins (level+1) fois // GetKmersAtLevel returns a KmerSet of k-mers seen at least (level+1) times
// level doit être dans [0, minFreq-1] // level doit être dans [0, minFreq-1]
func (ff *FrequencyFilter) GetKmersAtLevel(level int) *KmerSet { func (ff *FrequencyFilter) GetKmersAtLevel(level int) *KmerSet {
ks := ff.Get(level) ks := ff.Get(level)
@@ -97,7 +97,7 @@ func (ff *FrequencyFilter) GetKmersAtLevel(level int) *KmerSet {
return ks.Copy() return ks.Copy()
} }
// Stats retourne des statistiques sur les niveaux de fréquence // Stats returns statistics on frequency levels
func (ff *FrequencyFilter) Stats() FrequencyFilterStats { func (ff *FrequencyFilter) Stats() FrequencyFilterStats {
stats := FrequencyFilterStats{ stats := FrequencyFilterStats{
MinFreq: ff.MinFreq, MinFreq: ff.MinFreq,
@@ -110,7 +110,7 @@ func (ff *FrequencyFilter) Stats() FrequencyFilterStats {
sizeBytes := ks.MemoryUsage() sizeBytes := ks.MemoryUsage()
stats.Levels[i] = LevelStats{ stats.Levels[i] = LevelStats{
Level: i + 1, // Niveau 1 = freq ≥ 1 Level: i + 1, // Level 1 = freq ≥ 1
Cardinality: card, Cardinality: card,
SizeBytes: sizeBytes, SizeBytes: sizeBytes,
} }
@@ -118,25 +118,25 @@ func (ff *FrequencyFilter) Stats() FrequencyFilterStats {
stats.TotalBytes += sizeBytes stats.TotalBytes += sizeBytes
} }
// Le dernier niveau contient le résultat // The last level contains the result
stats.FilteredKmers = stats.Levels[ff.MinFreq-1].Cardinality stats.FilteredKmers = stats.Levels[ff.MinFreq-1].Cardinality
return stats return stats
} }
// FrequencyFilterStats contient les statistiques du filtre // FrequencyFilterStats contains the filter statistics
type FrequencyFilterStats struct { type FrequencyFilterStats struct {
MinFreq int MinFreq int
FilteredKmers uint64 // K-mers avec freq ≥ minFreq FilteredKmers uint64 // K-mers with freq ≥ minFreq
TotalBytes uint64 // Mémoire totale utilisée TotalBytes uint64 // Total memory used
Levels []LevelStats Levels []LevelStats
} }
// LevelStats contient les stats d'un niveau // LevelStats contains the stats of a level
type LevelStats struct { type LevelStats struct {
Level int // freq ≥ Level Level int // freq ≥ Level
Cardinality uint64 // Nombre de k-mers Cardinality uint64 // Number of k-mers
SizeBytes uint64 // Taille en bytes SizeBytes uint64 // Size in bytes
} }
func (ffs FrequencyFilterStats) String() string { func (ffs FrequencyFilterStats) String() string {
@@ -167,7 +167,7 @@ func (ff *FrequencyFilter) Clear() {
// BATCH PROCESSING // BATCH PROCESSING
// ================================== // ==================================
// AddSequences ajoute plusieurs séquences en batch // AddSequences adds multiple sequences in batch
func (ff *FrequencyFilter) AddSequences(sequences *obiseq.BioSequenceSlice) { func (ff *FrequencyFilter) AddSequences(sequences *obiseq.BioSequenceSlice) {
for _, seq := range *sequences { for _, seq := range *sequences {
ff.AddSequence(seq) ff.AddSequence(seq)
@@ -251,7 +251,7 @@ func (ff *FrequencyFilter) Contains(kmer uint64) bool {
return ff.Get(ff.MinFreq - 1).Contains(canonical) return ff.Get(ff.MinFreq - 1).Contains(canonical)
} }
// GetFrequency retourne la fréquence approximative d'un k-mer // GetFrequency returns the approximate frequency of a k-mer
// Retourne le niveau maximum atteint (freq ≥ niveau) // Retourne le niveau maximum atteint (freq ≥ niveau)
func (ff *FrequencyFilter) GetFrequency(kmer uint64) int { func (ff *FrequencyFilter) GetFrequency(kmer uint64) int {
canonical := CanonicalKmer(kmer, ff.K()) canonical := CanonicalKmer(kmer, ff.K())
@@ -268,16 +268,16 @@ func (ff *FrequencyFilter) GetFrequency(kmer uint64) int {
return freq return freq
} }
// Len retourne le nombre de k-mers filtrés ou à un niveau spécifique // Len returns the number of filtered k-mers or at a specific level
// Sans argument: retourne le nombre de k-mers avec freq ≥ minFreq (dernier niveau) // Without argument: returns the number of k-mers with freq ≥ minFreq (last level)
// Avec argument level: retourne le nombre de k-mers avec freq ≥ (level+1) // With argument level: returns the number of k-mers with freq ≥ (level+1)
// Exemple: Len() pour les k-mers filtrés, Len(2) pour freq ≥ 3 // Exemple: Len() pour les k-mers filtrés, Len(2) pour freq ≥ 3
// (héritée de KmerSetGroup mais redéfinie pour la documentation) // (héritée de KmerSetGroup mais redéfinie pour la documentation)
func (ff *FrequencyFilter) Len(level ...int) uint64 { func (ff *FrequencyFilter) Len(level ...int) uint64 {
return ff.KmerSetGroup.Len(level...) return ff.KmerSetGroup.Len(level...)
} }
// MemoryUsage retourne l'utilisation mémoire en bytes // MemoryUsage returns memory usage in bytes
// (héritée de KmerSetGroup mais redéfinie pour clarté) // (héritée de KmerSetGroup mais redéfinie pour clarté)
func (ff *FrequencyFilter) MemoryUsage() uint64 { func (ff *FrequencyFilter) MemoryUsage() uint64 {
return ff.KmerSetGroup.MemoryUsage() return ff.KmerSetGroup.MemoryUsage()

View File

@@ -7,16 +7,16 @@ import (
"github.com/RoaringBitmap/roaring/roaring64" "github.com/RoaringBitmap/roaring/roaring64"
) )
// KmerSet encapsule un ensemble de k-mers stockés dans un Roaring Bitmap // KmerSet wraps a set of k-mers stored in a Roaring Bitmap
// Fournit des méthodes utilitaires pour manipuler des ensembles de k-mers // Provides utility methods for manipulating k-mer sets
type KmerSet struct { type KmerSet struct {
id string // Identifiant unique du KmerSet id string // Unique identifier of the KmerSet
k int // Taille des k-mers (immutable) k int // Size of k-mers (immutable)
bitmap *roaring64.Bitmap // Bitmap contenant les k-mers bitmap *roaring64.Bitmap // Bitmap containing the k-mers
Metadata map[string]interface{} // Métadonnées utilisateur (clé=valeur atomique) Metadata map[string]interface{} // User metadata (key=atomic value)
} }
// NewKmerSet crée un nouveau KmerSet vide // NewKmerSet creates a new empty KmerSet
func NewKmerSet(k int) *KmerSet { func NewKmerSet(k int) *KmerSet {
return &KmerSet{ return &KmerSet{
k: k, k: k,
@@ -25,7 +25,7 @@ func NewKmerSet(k int) *KmerSet {
} }
} }
// NewKmerSetFromBitmap crée un KmerSet à partir d'un bitmap existant // NewKmerSetFromBitmap creates a KmerSet from an existing bitmap
func NewKmerSetFromBitmap(k int, bitmap *roaring64.Bitmap) *KmerSet { func NewKmerSetFromBitmap(k int, bitmap *roaring64.Bitmap) *KmerSet {
return &KmerSet{ return &KmerSet{
k: k, k: k,
@@ -34,40 +34,40 @@ func NewKmerSetFromBitmap(k int, bitmap *roaring64.Bitmap) *KmerSet {
} }
} }
// K retourne la taille des k-mers (immutable) // K returns the size of k-mers (immutable)
func (ks *KmerSet) K() int { func (ks *KmerSet) K() int {
return ks.k return ks.k
} }
// AddKmerCode ajoute un k-mer encodé à l'ensemble // AddKmerCode adds an encoded k-mer to the set
func (ks *KmerSet) AddKmerCode(kmer uint64) { func (ks *KmerSet) AddKmerCode(kmer uint64) {
ks.bitmap.Add(kmer) ks.bitmap.Add(kmer)
} }
// AddCanonicalKmerCode ajoute un k-mer encodé canonique à l'ensemble // AddCanonicalKmerCode adds an encoded canonical k-mer to the set
func (ks *KmerSet) AddCanonicalKmerCode(kmer uint64) { func (ks *KmerSet) AddCanonicalKmerCode(kmer uint64) {
canonical := CanonicalKmer(kmer, ks.k) canonical := CanonicalKmer(kmer, ks.k)
ks.bitmap.Add(canonical) ks.bitmap.Add(canonical)
} }
// AddKmer ajoute un k-mer à l'ensemble en encodant la séquence // AddKmer adds a k-mer to the set by encoding the sequence
// La séquence doit avoir exactement k nucléotides // The sequence must have exactly k nucleotides
// Zero-allocation: encode directement sans créer de slice intermédiaire // Zero-allocation: encodes directly without creating an intermediate slice
func (ks *KmerSet) AddKmer(seq []byte) { func (ks *KmerSet) AddKmer(seq []byte) {
kmer := EncodeKmer(seq, ks.k) kmer := EncodeKmer(seq, ks.k)
ks.bitmap.Add(kmer) ks.bitmap.Add(kmer)
} }
// AddCanonicalKmer ajoute un k-mer canonique à l'ensemble en encodant la séquence // AddCanonicalKmer adds a canonical k-mer to the set by encoding the sequence
// La séquence doit avoir exactement k nucléotides // The sequence must have exactly k nucleotides
// Zero-allocation: encode directement en forme canonique sans créer de slice intermédiaire // Zero-allocation: encodes directly in canonical form without creating an intermediate slice
func (ks *KmerSet) AddCanonicalKmer(seq []byte) { func (ks *KmerSet) AddCanonicalKmer(seq []byte) {
canonical := EncodeCanonicalKmer(seq, ks.k) canonical := EncodeCanonicalKmer(seq, ks.k)
ks.bitmap.Add(canonical) ks.bitmap.Add(canonical)
} }
// AddSequence ajoute tous les k-mers d'une séquence à l'ensemble // AddSequence adds all k-mers from a sequence to the set
// Utilise un itérateur pour éviter l'allocation d'un vecteur intermédiaire // Uses an iterator to avoid allocating an intermediate vector
func (ks *KmerSet) AddSequence(seq *obiseq.BioSequence) { func (ks *KmerSet) AddSequence(seq *obiseq.BioSequence) {
rawSeq := seq.Sequence() rawSeq := seq.Sequence()
for canonical := range IterCanonicalKmers(rawSeq, ks.k) { for canonical := range IterCanonicalKmers(rawSeq, ks.k) {
@@ -75,36 +75,36 @@ func (ks *KmerSet) AddSequence(seq *obiseq.BioSequence) {
} }
} }
// AddSequences ajoute tous les k-mers de plusieurs séquences en batch // AddSequences adds all k-mers from multiple sequences in batch
func (ks *KmerSet) AddSequences(sequences *obiseq.BioSequenceSlice) { func (ks *KmerSet) AddSequences(sequences *obiseq.BioSequenceSlice) {
for _, seq := range *sequences { for _, seq := range *sequences {
ks.AddSequence(seq) ks.AddSequence(seq)
} }
} }
// Contains vérifie si un k-mer est dans l'ensemble // Contains checks if a k-mer is in the set
func (ks *KmerSet) Contains(kmer uint64) bool { func (ks *KmerSet) Contains(kmer uint64) bool {
return ks.bitmap.Contains(kmer) return ks.bitmap.Contains(kmer)
} }
// Len retourne le nombre de k-mers dans l'ensemble // Len returns the number of k-mers in the set
func (ks *KmerSet) Len() uint64 { func (ks *KmerSet) Len() uint64 {
return ks.bitmap.GetCardinality() return ks.bitmap.GetCardinality()
} }
// MemoryUsage retourne l'utilisation mémoire en bytes // MemoryUsage returns memory usage in bytes
func (ks *KmerSet) MemoryUsage() uint64 { func (ks *KmerSet) MemoryUsage() uint64 {
return ks.bitmap.GetSizeInBytes() return ks.bitmap.GetSizeInBytes()
} }
// Clear vide l'ensemble // Clear empties the set
func (ks *KmerSet) Clear() { func (ks *KmerSet) Clear() {
ks.bitmap.Clear() ks.bitmap.Clear()
} }
// Copy crée une copie de l'ensemble (cohérent avec BioSequence.Copy) // Copy creates a copy of the set (consistent with BioSequence.Copy)
func (ks *KmerSet) Copy() *KmerSet { func (ks *KmerSet) Copy() *KmerSet {
// Copier les métadonnées // Copy metadata
metadata := make(map[string]interface{}, len(ks.Metadata)) metadata := make(map[string]interface{}, len(ks.Metadata))
for k, v := range ks.Metadata { for k, v := range ks.Metadata {
metadata[k] = v metadata[k] = v
@@ -118,17 +118,17 @@ func (ks *KmerSet) Copy() *KmerSet {
} }
} }
// Id retourne l'identifiant du KmerSet (cohérent avec BioSequence.Id) // Id returns the identifier of the KmerSet (consistent with BioSequence.Id)
func (ks *KmerSet) Id() string { func (ks *KmerSet) Id() string {
return ks.id return ks.id
} }
// SetId définit l'identifiant du KmerSet (cohérent avec BioSequence.SetId) // SetId sets the identifier of the KmerSet (consistent with BioSequence.SetId)
func (ks *KmerSet) SetId(id string) { func (ks *KmerSet) SetId(id string) {
ks.id = id ks.id = id
} }
// Union retourne l'union de cet ensemble avec un autre // Union returns the union of this set with another
func (ks *KmerSet) Union(other *KmerSet) *KmerSet { func (ks *KmerSet) Union(other *KmerSet) *KmerSet {
if ks.k != other.k { if ks.k != other.k {
panic(fmt.Sprintf("Cannot union KmerSets with different k values: %d vs %d", ks.k, other.k)) panic(fmt.Sprintf("Cannot union KmerSets with different k values: %d vs %d", ks.k, other.k))
@@ -138,7 +138,7 @@ func (ks *KmerSet) Union(other *KmerSet) *KmerSet {
return NewKmerSetFromBitmap(ks.k, result) return NewKmerSetFromBitmap(ks.k, result)
} }
// Intersect retourne l'intersection de cet ensemble avec un autre // Intersect returns the intersection of this set with another
func (ks *KmerSet) Intersect(other *KmerSet) *KmerSet { func (ks *KmerSet) Intersect(other *KmerSet) *KmerSet {
if ks.k != other.k { if ks.k != other.k {
panic(fmt.Sprintf("Cannot intersect KmerSets with different k values: %d vs %d", ks.k, other.k)) panic(fmt.Sprintf("Cannot intersect KmerSets with different k values: %d vs %d", ks.k, other.k))
@@ -148,7 +148,7 @@ func (ks *KmerSet) Intersect(other *KmerSet) *KmerSet {
return NewKmerSetFromBitmap(ks.k, result) return NewKmerSetFromBitmap(ks.k, result)
} }
// Difference retourne la différence de cet ensemble avec un autre (this - other) // Difference returns the difference of this set with another (this - other)
func (ks *KmerSet) Difference(other *KmerSet) *KmerSet { func (ks *KmerSet) Difference(other *KmerSet) *KmerSet {
if ks.k != other.k { if ks.k != other.k {
panic(fmt.Sprintf("Cannot subtract KmerSets with different k values: %d vs %d", ks.k, other.k)) panic(fmt.Sprintf("Cannot subtract KmerSets with different k values: %d vs %d", ks.k, other.k))
@@ -158,12 +158,12 @@ func (ks *KmerSet) Difference(other *KmerSet) *KmerSet {
return NewKmerSetFromBitmap(ks.k, result) return NewKmerSetFromBitmap(ks.k, result)
} }
// Iterator retourne un itérateur sur tous les k-mers de l'ensemble // Iterator returns an iterator over all k-mers in the set
func (ks *KmerSet) Iterator() roaring64.IntIterable64 { func (ks *KmerSet) Iterator() roaring64.IntIterable64 {
return ks.bitmap.Iterator() return ks.bitmap.Iterator()
} }
// Bitmap retourne le bitmap sous-jacent (pour compatibilité) // Bitmap returns the underlying bitmap (for compatibility)
func (ks *KmerSet) Bitmap() *roaring64.Bitmap { func (ks *KmerSet) Bitmap() *roaring64.Bitmap {
return ks.bitmap return ks.bitmap
} }

View File

@@ -32,7 +32,7 @@ func (ks *KmerSet) GetAttribute(key string) (interface{}, bool) {
} }
} }
// SetAttribute définit la valeur d'un attribut // SetAttribute sets the value of an attribute
// Cas particuliers: "id" utilise SetId(), "k" est immutable (panique) // Cas particuliers: "id" utilise SetId(), "k" est immutable (panique)
func (ks *KmerSet) SetAttribute(key string, value interface{}) { func (ks *KmerSet) SetAttribute(key string, value interface{}) {
switch key { switch key {
@@ -153,7 +153,7 @@ func (ks *KmerSet) GetBoolAttribute(key string) (bool, bool) {
return false, false return false, false
} }
// AttributeKeys retourne l'ensemble des clés d'attributs // AttributeKeys returns the set of attribute keys
func (ks *KmerSet) AttributeKeys() obiutils.Set[string] { func (ks *KmerSet) AttributeKeys() obiutils.Set[string] {
keys := obiutils.MakeSet[string]() keys := obiutils.MakeSet[string]()
for key := range ks.Metadata { for key := range ks.Metadata {
@@ -162,7 +162,7 @@ func (ks *KmerSet) AttributeKeys() obiutils.Set[string] {
return keys return keys
} }
// Keys retourne l'ensemble des clés d'attributs (alias de AttributeKeys) // Keys returns the set of attribute keys (alias of AttributeKeys)
func (ks *KmerSet) Keys() obiutils.Set[string] { func (ks *KmerSet) Keys() obiutils.Set[string] {
return ks.AttributeKeys() return ks.AttributeKeys()
} }
@@ -192,7 +192,7 @@ func (ksg *KmerSetGroup) GetAttribute(key string) (interface{}, bool) {
} }
} }
// SetAttribute définit la valeur d'un attribut du groupe // SetAttribute sets the value of an attribute du groupe
// Cas particuliers: "id" utilise SetId(), "k" est immutable (panique) // Cas particuliers: "id" utilise SetId(), "k" est immutable (panique)
func (ksg *KmerSetGroup) SetAttribute(key string, value interface{}) { func (ksg *KmerSetGroup) SetAttribute(key string, value interface{}) {
switch key { switch key {
@@ -313,7 +313,7 @@ func (ksg *KmerSetGroup) GetBoolAttribute(key string) (bool, bool) {
return false, false return false, false
} }
// AttributeKeys retourne l'ensemble des clés d'attributs du groupe // AttributeKeys returns the set of attribute keys du groupe
func (ksg *KmerSetGroup) AttributeKeys() obiutils.Set[string] { func (ksg *KmerSetGroup) AttributeKeys() obiutils.Set[string] {
keys := obiutils.MakeSet[string]() keys := obiutils.MakeSet[string]()
for key := range ksg.Metadata { for key := range ksg.Metadata {
@@ -322,7 +322,7 @@ func (ksg *KmerSetGroup) AttributeKeys() obiutils.Set[string] {
return keys return keys
} }
// Keys retourne l'ensemble des clés d'attributs du groupe (alias) // Keys returns the set of group attribute keys (alias)
func (ksg *KmerSetGroup) Keys() obiutils.Set[string] { func (ksg *KmerSetGroup) Keys() obiutils.Set[string] {
return ksg.AttributeKeys() return ksg.AttributeKeys()
} }
@@ -342,7 +342,7 @@ func (ksg *KmerSetGroup) Keys() obiutils.Set[string] {
// ksg.SetAttribute("name", "FrequencyFilter") // ksg.SetAttribute("name", "FrequencyFilter")
// name, ok := ksg.GetStringAttribute("name") // name, ok := ksg.GetStringAttribute("name")
// AllAttributeKeys retourne toutes les clés d'attributs uniques du groupe ET de tous ses sets // AllAttributeKeys returns all unique attribute keys of the group AND all its sets
func (ksg *KmerSetGroup) AllAttributeKeys() obiutils.Set[string] { func (ksg *KmerSetGroup) AllAttributeKeys() obiutils.Set[string] {
keys := obiutils.MakeSet[string]() keys := obiutils.MakeSet[string]()

View File

@@ -6,16 +6,16 @@ import (
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq" "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
) )
// KmerSetGroup représente un vecteur de KmerSet // KmerSetGroup represents a vector of KmerSet
// Utilisé pour gérer plusieurs ensembles de k-mers (par exemple, par niveau de fréquence) // Used to manage multiple k-mer sets (for example, by frequency level)
type KmerSetGroup struct { type KmerSetGroup struct {
id string // Identifiant unique du KmerSetGroup id string // Unique identifier of the KmerSetGroup
k int // Taille des k-mers (immutable) k int // Size of k-mers (immutable)
sets []*KmerSet // Vecteur de KmerSet sets []*KmerSet // Vector of KmerSet
Metadata map[string]interface{} // Métadonnées du groupe (pas des sets individuels) Metadata map[string]interface{} // Group metadata (not individual sets)
} }
// NewKmerSetGroup crée un nouveau groupe de n KmerSets // NewKmerSetGroup creates a new group of n KmerSets
func NewKmerSetGroup(k int, n int) *KmerSetGroup { func NewKmerSetGroup(k int, n int) *KmerSetGroup {
if n < 1 { if n < 1 {
panic("KmerSetGroup size must be >= 1") panic("KmerSetGroup size must be >= 1")
@@ -33,18 +33,18 @@ func NewKmerSetGroup(k int, n int) *KmerSetGroup {
} }
} }
// K retourne la taille des k-mers (immutable) // K returns the size of k-mers (immutable)
func (ksg *KmerSetGroup) K() int { func (ksg *KmerSetGroup) K() int {
return ksg.k return ksg.k
} }
// Size retourne le nombre de KmerSet dans le groupe // Size returns the number of KmerSet in the group
func (ksg *KmerSetGroup) Size() int { func (ksg *KmerSetGroup) Size() int {
return len(ksg.sets) return len(ksg.sets)
} }
// Get retourne le KmerSet à l'index donné // Get returns the KmerSet at the given index
// Retourne nil si l'index est invalide // Returns nil if the index is invalid
func (ksg *KmerSetGroup) Get(index int) *KmerSet { func (ksg *KmerSetGroup) Get(index int) *KmerSet {
if index < 0 || index >= len(ksg.sets) { if index < 0 || index >= len(ksg.sets) {
return nil return nil
@@ -52,8 +52,8 @@ func (ksg *KmerSetGroup) Get(index int) *KmerSet {
return ksg.sets[index] return ksg.sets[index]
} }
// Set remplace le KmerSet à l'index donné // Set replaces the KmerSet at the given index
// Panique si l'index est invalide ou si le k ne correspond pas // Panics if the index is invalid or if k does not match
func (ksg *KmerSetGroup) Set(index int, ks *KmerSet) { func (ksg *KmerSetGroup) Set(index int, ks *KmerSet) {
if index < 0 || index >= len(ksg.sets) { if index < 0 || index >= len(ksg.sets) {
panic(fmt.Sprintf("Index out of bounds: %d (size: %d)", index, len(ksg.sets))) panic(fmt.Sprintf("Index out of bounds: %d (size: %d)", index, len(ksg.sets)))
@@ -64,16 +64,16 @@ func (ksg *KmerSetGroup) Set(index int, ks *KmerSet) {
ksg.sets[index] = ks ksg.sets[index] = ks
} }
// Len retourne le nombre de k-mers dans un KmerSet spécifique // Len returns the number of k-mers in a specific KmerSet
// Sans argument: retourne le nombre de k-mers dans le dernier KmerSet // Without argument: returns the number of k-mers in the last KmerSet
// Avec argument index: retourne le nombre de k-mers dans le KmerSet à cet index // With argument index: returns the number of k-mers in the KmerSet at this index
func (ksg *KmerSetGroup) Len(index ...int) uint64 { func (ksg *KmerSetGroup) Len(index ...int) uint64 {
if len(index) == 0 { if len(index) == 0 {
// Sans argument: dernier KmerSet // Without argument: last KmerSet
return ksg.sets[len(ksg.sets)-1].Len() return ksg.sets[len(ksg.sets)-1].Len()
} }
// Avec argument: KmerSet spécifique // With argument: specific KmerSet
idx := index[0] idx := index[0]
if idx < 0 || idx >= len(ksg.sets) { if idx < 0 || idx >= len(ksg.sets) {
return 0 return 0
@@ -81,7 +81,7 @@ func (ksg *KmerSetGroup) Len(index ...int) uint64 {
return ksg.sets[idx].Len() return ksg.sets[idx].Len()
} }
// MemoryUsage retourne l'utilisation mémoire totale en bytes // MemoryUsage returns the total memory usage in bytes
func (ksg *KmerSetGroup) MemoryUsage() uint64 { func (ksg *KmerSetGroup) MemoryUsage() uint64 {
total := uint64(0) total := uint64(0)
for _, ks := range ksg.sets { for _, ks := range ksg.sets {
@@ -90,21 +90,21 @@ func (ksg *KmerSetGroup) MemoryUsage() uint64 {
return total return total
} }
// Clear vide tous les KmerSet du groupe // Clear empties all KmerSet in the group
func (ksg *KmerSetGroup) Clear() { func (ksg *KmerSetGroup) Clear() {
for _, ks := range ksg.sets { for _, ks := range ksg.sets {
ks.Clear() ks.Clear()
} }
} }
// Copy crée une copie complète du groupe (cohérent avec BioSequence.Copy) // Copy creates a complete copy of the group (consistent with BioSequence.Copy)
func (ksg *KmerSetGroup) Copy() *KmerSetGroup { func (ksg *KmerSetGroup) Copy() *KmerSetGroup {
copiedSets := make([]*KmerSet, len(ksg.sets)) copiedSets := make([]*KmerSet, len(ksg.sets))
for i, ks := range ksg.sets { for i, ks := range ksg.sets {
copiedSets[i] = ks.Copy() // Copy chaque KmerSet avec ses métadonnées copiedSets[i] = ks.Copy() // Copy each KmerSet with its metadata
} }
// Copier les métadonnées du groupe // Copy group metadata
groupMetadata := make(map[string]interface{}, len(ksg.Metadata)) groupMetadata := make(map[string]interface{}, len(ksg.Metadata))
for k, v := range ksg.Metadata { for k, v := range ksg.Metadata {
groupMetadata[k] = v groupMetadata[k] = v
@@ -118,17 +118,17 @@ func (ksg *KmerSetGroup) Copy() *KmerSetGroup {
} }
} }
// Id retourne l'identifiant du KmerSetGroup (cohérent avec BioSequence.Id) // Id returns the identifier of the KmerSetGroup (consistent with BioSequence.Id)
func (ksg *KmerSetGroup) Id() string { func (ksg *KmerSetGroup) Id() string {
return ksg.id return ksg.id
} }
// SetId définit l'identifiant du KmerSetGroup (cohérent avec BioSequence.SetId) // SetId sets the identifier of the KmerSetGroup (consistent with BioSequence.SetId)
func (ksg *KmerSetGroup) SetId(id string) { func (ksg *KmerSetGroup) SetId(id string) {
ksg.id = id ksg.id = id
} }
// AddSequence ajoute tous les k-mers d'une séquence à un KmerSet spécifique // AddSequence adds all k-mers from a sequence to a specific KmerSet
func (ksg *KmerSetGroup) AddSequence(seq *obiseq.BioSequence, index int) { func (ksg *KmerSetGroup) AddSequence(seq *obiseq.BioSequence, index int) {
if index < 0 || index >= len(ksg.sets) { if index < 0 || index >= len(ksg.sets) {
panic(fmt.Sprintf("Index out of bounds: %d (size: %d)", index, len(ksg.sets))) panic(fmt.Sprintf("Index out of bounds: %d (size: %d)", index, len(ksg.sets)))
@@ -136,7 +136,7 @@ func (ksg *KmerSetGroup) AddSequence(seq *obiseq.BioSequence, index int) {
ksg.sets[index].AddSequence(seq) ksg.sets[index].AddSequence(seq)
} }
// AddSequences ajoute tous les k-mers de plusieurs séquences à un KmerSet spécifique // AddSequences adds all k-mers from multiple sequences to a specific KmerSet
func (ksg *KmerSetGroup) AddSequences(sequences *obiseq.BioSequenceSlice, index int) { func (ksg *KmerSetGroup) AddSequences(sequences *obiseq.BioSequenceSlice, index int) {
if index < 0 || index >= len(ksg.sets) { if index < 0 || index >= len(ksg.sets) {
panic(fmt.Sprintf("Index out of bounds: %d (size: %d)", index, len(ksg.sets))) panic(fmt.Sprintf("Index out of bounds: %d (size: %d)", index, len(ksg.sets)))
@@ -144,8 +144,8 @@ func (ksg *KmerSetGroup) AddSequences(sequences *obiseq.BioSequenceSlice, index
ksg.sets[index].AddSequences(sequences) ksg.sets[index].AddSequences(sequences)
} }
// Union retourne l'union de tous les KmerSet du groupe // Union returns the union of all KmerSet in the group
// Optimisation: part du plus grand ensemble pour minimiser les opérations // Optimization: starts from the largest set to minimize operations
func (ksg *KmerSetGroup) Union() *KmerSet { func (ksg *KmerSetGroup) Union() *KmerSet {
if len(ksg.sets) == 0 { if len(ksg.sets) == 0 {
return NewKmerSet(ksg.k) return NewKmerSet(ksg.k)
@@ -155,7 +155,7 @@ func (ksg *KmerSetGroup) Union() *KmerSet {
return ksg.sets[0].Copy() return ksg.sets[0].Copy()
} }
// Trouver l'index du plus grand ensemble (celui avec le plus de k-mers) // Find the index of the largest set (the one with the most k-mers)
maxIdx := 0 maxIdx := 0
maxCard := ksg.sets[0].Len() maxCard := ksg.sets[0].Len()
for i := 1; i < len(ksg.sets); i++ { for i := 1; i < len(ksg.sets); i++ {
@@ -166,7 +166,7 @@ func (ksg *KmerSetGroup) Union() *KmerSet {
} }
} }
// Copier le plus grand ensemble et faire les unions in-place // Copy the largest set and perform unions in-place
result := ksg.sets[maxIdx].bitmap.Clone() result := ksg.sets[maxIdx].bitmap.Clone()
for i := 0; i < len(ksg.sets); i++ { for i := 0; i < len(ksg.sets); i++ {
if i != maxIdx { if i != maxIdx {
@@ -177,8 +177,8 @@ func (ksg *KmerSetGroup) Union() *KmerSet {
return NewKmerSetFromBitmap(ksg.k, result) return NewKmerSetFromBitmap(ksg.k, result)
} }
// Intersect retourne l'intersection de tous les KmerSet du groupe // Intersect returns the intersection of all KmerSet in the group
// Optimisation: part du plus petit ensemble pour minimiser les opérations // Optimization: starts from the smallest set to minimize operations
func (ksg *KmerSetGroup) Intersect() *KmerSet { func (ksg *KmerSetGroup) Intersect() *KmerSet {
if len(ksg.sets) == 0 { if len(ksg.sets) == 0 {
return NewKmerSet(ksg.k) return NewKmerSet(ksg.k)
@@ -188,7 +188,7 @@ func (ksg *KmerSetGroup) Intersect() *KmerSet {
return ksg.sets[0].Copy() return ksg.sets[0].Copy()
} }
// Trouver l'index du plus petit ensemble (celui avec le moins de k-mers) // Find the index of the smallest set (the one with the fewest k-mers)
minIdx := 0 minIdx := 0
minCard := ksg.sets[0].Len() minCard := ksg.sets[0].Len()
for i := 1; i < len(ksg.sets); i++ { for i := 1; i < len(ksg.sets); i++ {
@@ -199,7 +199,7 @@ func (ksg *KmerSetGroup) Intersect() *KmerSet {
} }
} }
// Copier le plus petit ensemble et faire les intersections in-place // Copy the smallest set and perform intersections in-place
result := ksg.sets[minIdx].bitmap.Clone() result := ksg.sets[minIdx].bitmap.Clone()
for i := 0; i < len(ksg.sets); i++ { for i := 0; i < len(ksg.sets); i++ {
if i != minIdx { if i != minIdx {
@@ -210,18 +210,18 @@ func (ksg *KmerSetGroup) Intersect() *KmerSet {
return NewKmerSetFromBitmap(ksg.k, result) return NewKmerSetFromBitmap(ksg.k, result)
} }
// Stats retourne des statistiques pour chaque KmerSet du groupe // Stats returns statistics for each KmerSet in the group
type KmerSetGroupStats struct { type KmerSetGroupStats struct {
K int K int
Size int // Nombre de KmerSet Size int // Number of KmerSet
TotalBytes uint64 // Mémoire totale utilisée TotalBytes uint64 // Total memory used
Sets []KmerSetStats // Stats de chaque KmerSet Sets []KmerSetStats // Stats of each KmerSet
} }
type KmerSetStats struct { type KmerSetStats struct {
Index int // Index du KmerSet dans le groupe Index int // Index of the KmerSet in the group
Len uint64 // Nombre de k-mers Len uint64 // Number of k-mers
SizeBytes uint64 // Taille en bytes SizeBytes uint64 // Size in bytes
} }
func (ksg *KmerSetGroup) Stats() KmerSetGroupStats { func (ksg *KmerSetGroup) Stats() KmerSetGroupStats {

View File

@@ -11,7 +11,7 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
// MetadataFormat représente le format de sérialisation des métadonnées // MetadataFormat represents the metadata serialization format
type MetadataFormat int type MetadataFormat int
const ( const (
@@ -20,7 +20,7 @@ const (
FormatJSON FormatJSON
) )
// String retourne l'extension de fichier pour le format // String returns the file extension for the format
func (f MetadataFormat) String() string { func (f MetadataFormat) String() string {
switch f { switch f {
case FormatTOML: case FormatTOML: