mirror of
https://github.com/metabarcoding/obitools4.git
synced 2025-06-29 16:20:46 +00:00
Merge obiminion and obiconsensus
Former-commit-id: 49d65d671e9fe4454de60c20507c3d8df6e9c51c
This commit is contained in:
@ -16,7 +16,6 @@ func main() {
|
|||||||
optionParser := obioptions.GenerateOptionParser(obiconsensus.OptionSet)
|
optionParser := obioptions.GenerateOptionParser(obiconsensus.OptionSet)
|
||||||
|
|
||||||
_, args := optionParser(os.Args)
|
_, args := optionParser(os.Args)
|
||||||
obiconvert.SetFullFileBatch()
|
|
||||||
|
|
||||||
fs, err := obiconvert.CLIReadBioSequences(args...)
|
fs, err := obiconvert.CLIReadBioSequences(args...)
|
||||||
|
|
||||||
@ -25,8 +24,9 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
consensus := obiconsensus.Consensus(fs)
|
cleaned := obiconsensus.CLIOBIMinion(fs)
|
||||||
obiconvert.CLIWriteBioSequences(consensus, true)
|
|
||||||
|
obiconvert.CLIWriteBioSequences(cleaned, true)
|
||||||
|
|
||||||
obiiter.WaitForLastPipe()
|
obiiter.WaitForLastPipe()
|
||||||
|
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiiter"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiconvert"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiminion"
|
|
||||||
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obioptions"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
optionParser := obioptions.GenerateOptionParser(obiminion.OptionSet)
|
|
||||||
|
|
||||||
_, args := optionParser(os.Args)
|
|
||||||
|
|
||||||
fs, err := obiconvert.CLIReadBioSequences(args...)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Cannot open file (%v)", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
cleaned := obiminion.CLIOBIMinion(fs)
|
|
||||||
|
|
||||||
obiconvert.CLIWriteBioSequences(cleaned, true)
|
|
||||||
|
|
||||||
obiiter.WaitForLastPipe()
|
|
||||||
|
|
||||||
}
|
|
@ -6,12 +6,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiutils"
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiutils"
|
||||||
"github.com/daichi-m/go18ds/sets/linkedhashset"
|
|
||||||
"github.com/daichi-m/go18ds/stacks/arraystack"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -397,6 +396,10 @@ func (graph *DeBruijnGraph) append(sequence []byte, current uint64, weight int)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Push appends a BioSequence to the DeBruijnGraph.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - sequence: a pointer to a BioSequence containing the sequence to be added.
|
||||||
func (graph *DeBruijnGraph) Push(sequence *obiseq.BioSequence) {
|
func (graph *DeBruijnGraph) Push(sequence *obiseq.BioSequence) {
|
||||||
s := sequence.Sequence() // Get the sequence as a byte slice
|
s := sequence.Sequence() // Get the sequence as a byte slice
|
||||||
w := sequence.Count() // Get the weight of the sequence
|
w := sequence.Count() // Get the weight of the sequence
|
||||||
@ -493,45 +496,19 @@ func (graph *DeBruijnGraph) Gml() string {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fonction tri_topologique(G, V):
|
// WriteGml writes the DeBruijnGraph to a GML file.
|
||||||
// T <- une liste vide pour stocker l'ordre topologique
|
//
|
||||||
// S <- une pile vide pour stocker les nœuds sans prédécesseurs
|
// filename: the name of the file to write the GML representation to.
|
||||||
// pour chaque nœud v dans V:
|
// error: an error if any occurs during the file creation or writing process.
|
||||||
// si Pred(v) est vide:
|
func (graph *DeBruijnGraph) WriteGml(filename string) error {
|
||||||
// empiler S avec v
|
|
||||||
// tant que S n'est pas vide:
|
|
||||||
// nœud <- dépiler S
|
|
||||||
// ajouter nœud à T
|
|
||||||
// pour chaque successeur s de nœud:
|
|
||||||
// supprimer l'arc (nœud, s) de G
|
|
||||||
// si Pred(s) est vide:
|
|
||||||
// empiler S avec s
|
|
||||||
// si G contient encore des arcs:
|
|
||||||
// renvoyer une erreur (le graphe contient au moins un cycle)
|
|
||||||
// sinon:
|
|
||||||
// renvoyer T (l'ordre topologique)
|
|
||||||
|
|
||||||
// A topological sort of the graph.
|
f, err := os.Create(filename)
|
||||||
func (g *DeBruijnGraph) PartialOrder() *linkedhashset.Set[uint64] {
|
if err != nil {
|
||||||
S := arraystack.New[uint64]()
|
return err
|
||||||
T := linkedhashset.New[uint64]()
|
|
||||||
|
|
||||||
for v := range g.graph {
|
|
||||||
if len(g.Previouses(v)) == 0 {
|
|
||||||
S.Push(v)
|
|
||||||
}
|
}
|
||||||
}
|
defer f.Close()
|
||||||
|
_, err = f.WriteString(graph.Gml())
|
||||||
for !S.Empty() {
|
return err
|
||||||
v, _ := S.Pop()
|
|
||||||
T.Add(v)
|
|
||||||
for _, w := range g.Nexts(v) {
|
|
||||||
if T.Contains(g.Previouses(w)...) {
|
|
||||||
S.Push(w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return T
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculating the hamming distance between two k-mers.
|
// Calculating the hamming distance between two k-mers.
|
||||||
|
@ -5,14 +5,21 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sync"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obialign"
|
||||||
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiformats"
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiformats"
|
||||||
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obigraph"
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiiter"
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiiter"
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obikmer"
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obikmer"
|
||||||
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obioptions"
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obisuffix"
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obisuffix"
|
||||||
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiannotate"
|
||||||
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiconvert"
|
||||||
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiuniq"
|
||||||
|
"github.com/schollz/progressbar/v3"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BuildConsensus(seqs obiseq.BioSequenceSlice,
|
func BuildConsensus(seqs obiseq.BioSequenceSlice,
|
||||||
@ -111,12 +118,198 @@ func BuildConsensus(seqs obiseq.BioSequenceSlice,
|
|||||||
return seq, err
|
return seq, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Consensus(iterator obiiter.IBioSequence) obiiter.IBioSequence {
|
// SampleWeight calculates the weight of a sample based on the statistics of a sequence.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - seqs: a pointer to BioSequenceSlice representing the sequences (*BioSequenceSlice)
|
||||||
|
// - sample: the sample for which the weight is calculated (string)
|
||||||
|
// - sample_key: the key used to access the sample's statistics (string)
|
||||||
|
// Return type: a function that takes an integer index and returns the weight of the sample at that index (func(int) int)
|
||||||
|
func SampleWeight(seqs *obiseq.BioSequenceSlice, sample, sample_key string) func(int) float64 {
|
||||||
|
|
||||||
|
f := func(i int) float64 {
|
||||||
|
|
||||||
|
stats := (*seqs)[i].StatsOn(sample_key, "NA")
|
||||||
|
|
||||||
|
if value, ok := stats[sample]; ok {
|
||||||
|
return float64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// SeqBySamples sorts the sequences by samples.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - seqs: a pointer to BioSequenceSlice representing the sequences (*BioSequenceSlice)
|
||||||
|
// - sample_key: a string representing the sample key (string)
|
||||||
|
//
|
||||||
|
// Return type:
|
||||||
|
// - map[string]BioSequenceSlice: a map indexed by sample names, each containing a slice of BioSequence objects (map[string]BioSequenceSlice)
|
||||||
|
func SeqBySamples(seqs obiseq.BioSequenceSlice, sample_key string) map[string]*obiseq.BioSequenceSlice {
|
||||||
|
|
||||||
|
samples := make(map[string]*obiseq.BioSequenceSlice)
|
||||||
|
|
||||||
|
for _, s := range seqs {
|
||||||
|
if s.HasStatsOn(sample_key) {
|
||||||
|
stats := s.StatsOn(sample_key, "NA")
|
||||||
|
for k := range stats {
|
||||||
|
if seqset, ok := samples[k]; ok {
|
||||||
|
*seqset = append(*seqset, s)
|
||||||
|
samples[k] = seqset
|
||||||
|
} else {
|
||||||
|
samples[k] = &obiseq.BioSequenceSlice{s}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if k, ok := s.GetStringAttribute(sample_key); ok {
|
||||||
|
if seqset, ok := samples[k]; ok {
|
||||||
|
*seqset = append(*seqset, s)
|
||||||
|
samples[k] = seqset
|
||||||
|
} else {
|
||||||
|
samples[k] = &obiseq.BioSequenceSlice{s}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return samples
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation struct {
|
||||||
|
Position int
|
||||||
|
SeqA byte
|
||||||
|
SeqB byte
|
||||||
|
Ratio float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildDiffSeqGraph(name, name_key string,
|
||||||
|
seqs *obiseq.BioSequenceSlice,
|
||||||
|
distmax, nworkers int) *obigraph.Graph[*obiseq.BioSequence, Mutation] {
|
||||||
|
graph := obigraph.NewGraphBuffer[*obiseq.BioSequence, Mutation](name, (*[]*obiseq.BioSequence)(seqs))
|
||||||
|
iseq := make(chan int)
|
||||||
|
defer graph.Close()
|
||||||
|
|
||||||
|
ls := len(*seqs)
|
||||||
|
|
||||||
|
sw := SampleWeight(seqs, name, name_key)
|
||||||
|
graph.Graph.VertexWeight = sw
|
||||||
|
|
||||||
|
waiting := sync.WaitGroup{}
|
||||||
|
waiting.Add(nworkers)
|
||||||
|
|
||||||
|
bar := (*progressbar.ProgressBar)(nil)
|
||||||
|
if obiconvert.CLIProgressBar() {
|
||||||
|
|
||||||
|
pbopt := make([]progressbar.Option, 0, 5)
|
||||||
|
pbopt = append(pbopt,
|
||||||
|
progressbar.OptionSetWriter(os.Stderr),
|
||||||
|
progressbar.OptionSetWidth(15),
|
||||||
|
progressbar.OptionShowIts(),
|
||||||
|
progressbar.OptionSetPredictTime(true),
|
||||||
|
progressbar.OptionSetDescription(fmt.Sprintf("[Build graph] on %s", name)),
|
||||||
|
)
|
||||||
|
|
||||||
|
bar = progressbar.NewOptions(len(*seqs), pbopt...)
|
||||||
|
}
|
||||||
|
|
||||||
|
computeEdges := func() {
|
||||||
|
defer waiting.Done()
|
||||||
|
for i := range iseq {
|
||||||
|
s1 := (*seqs)[i]
|
||||||
|
for j := i + 1; j < ls; j++ {
|
||||||
|
s2 := (*seqs)[j]
|
||||||
|
ratio := sw(i) / sw(j)
|
||||||
|
ok, pos, a1, a2 := obialign.D1Or0(s1, s2)
|
||||||
|
if ok >= 0 {
|
||||||
|
graph.AddEdge(i, j, &Mutation{pos, a1, a2, ratio})
|
||||||
|
} else if distmax > 1 {
|
||||||
|
lcs, lali := obialign.FastLCSScore(s1, s2, distmax, nil)
|
||||||
|
dist := lali - lcs
|
||||||
|
if lcs > 0 && dist <= distmax {
|
||||||
|
// log.Infof("Seq %s and %s: LCSScore: %d, dist: %d\n", s1.Id(), s2.Id(), lcs, dist)
|
||||||
|
graph.AddEdge(i, j, &Mutation{pos, a1, a2, ratio})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if bar != nil {
|
||||||
|
bar.Add(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < nworkers; i++ {
|
||||||
|
go computeEdges()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < ls; i++ {
|
||||||
|
iseq <- i
|
||||||
|
}
|
||||||
|
close(iseq)
|
||||||
|
|
||||||
|
waiting.Wait()
|
||||||
|
return graph.Graph
|
||||||
|
}
|
||||||
|
|
||||||
|
func MinionDenoise(graph *obigraph.Graph[*obiseq.BioSequence, Mutation],
|
||||||
|
sample_key string, kmer_size int) obiseq.BioSequenceSlice {
|
||||||
|
denoised := obiseq.MakeBioSequenceSlice(len(*graph.Vertices))
|
||||||
|
|
||||||
|
for i, v := range *graph.Vertices {
|
||||||
|
var err error
|
||||||
|
var clean *obiseq.BioSequence
|
||||||
|
degree := graph.Degree(i)
|
||||||
|
if degree > 4 {
|
||||||
|
pack := obiseq.MakeBioSequenceSlice(degree + 1)
|
||||||
|
for k, j := range graph.Neighbors(i) {
|
||||||
|
pack[k] = (*graph.Vertices)[j]
|
||||||
|
}
|
||||||
|
pack[degree] = v
|
||||||
|
clean, err = BuildConsensus(pack,
|
||||||
|
fmt.Sprintf("%s_consensus", v.Id()),
|
||||||
|
kmer_size,
|
||||||
|
CLISaveGraphToFiles(), CLIGraphFilesDirectory())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Warning(err)
|
||||||
|
clean = (*graph.Vertices)[i]
|
||||||
|
clean.SetAttribute("obiminion_consensus", false)
|
||||||
|
} else {
|
||||||
|
clean.SetAttribute("obiminion_consensus", true)
|
||||||
|
}
|
||||||
|
pack.Recycle(false)
|
||||||
|
} else {
|
||||||
|
clean = obiseq.NewBioSequence(v.Id(), v.Sequence(), v.Definition())
|
||||||
|
clean.SetAttribute("obiminion_consensus", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
clean.SetCount(int(graph.VertexWeight(i)))
|
||||||
|
clean.SetAttribute(sample_key, graph.Name)
|
||||||
|
|
||||||
|
denoised[i] = clean
|
||||||
|
}
|
||||||
|
|
||||||
|
return denoised
|
||||||
|
}
|
||||||
|
func CLIOBIMinion(itertator obiiter.IBioSequence) obiiter.IBioSequence {
|
||||||
|
dirname := CLIGraphFilesDirectory()
|
||||||
newIter := obiiter.MakeIBioSequence()
|
newIter := obiiter.MakeIBioSequence()
|
||||||
size := 10
|
|
||||||
|
db := itertator.Load()
|
||||||
|
|
||||||
|
log.Infof("Sequence dataset of %d sequeences loaded\n", len(db))
|
||||||
|
|
||||||
|
samples := SeqBySamples(db, CLISampleAttribute())
|
||||||
|
db.Recycle(false)
|
||||||
|
|
||||||
|
log.Infof("Dataset composed of %d samples\n", len(samples))
|
||||||
|
|
||||||
if CLISaveGraphToFiles() {
|
if CLISaveGraphToFiles() {
|
||||||
dirname := CLIGraphFilesDirectory()
|
|
||||||
if stat, err := os.Stat(dirname); err != nil || !stat.IsDir() {
|
if stat, err := os.Stat(dirname); err != nil || !stat.IsDir() {
|
||||||
// path does not exist or is not directory
|
// path does not exist or is not directory
|
||||||
os.RemoveAll(dirname)
|
os.RemoveAll(dirname)
|
||||||
@ -128,52 +321,60 @@ func Consensus(iterator obiiter.IBioSequence) obiiter.IBioSequence {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bar := (*progressbar.ProgressBar)(nil)
|
||||||
|
if obiconvert.CLIProgressBar() {
|
||||||
|
|
||||||
|
pbopt := make([]progressbar.Option, 0, 5)
|
||||||
|
pbopt = append(pbopt,
|
||||||
|
progressbar.OptionSetWriter(os.Stderr),
|
||||||
|
progressbar.OptionSetWidth(15),
|
||||||
|
progressbar.OptionShowIts(),
|
||||||
|
progressbar.OptionSetPredictTime(true),
|
||||||
|
progressbar.OptionSetDescription("[Filter graph on abundance ratio]"),
|
||||||
|
)
|
||||||
|
|
||||||
|
bar = progressbar.NewOptions(len(samples), pbopt...)
|
||||||
|
}
|
||||||
|
|
||||||
newIter.Add(1)
|
newIter.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
sample_order := 0
|
||||||
|
for sample, seqs := range samples {
|
||||||
|
graph := BuildDiffSeqGraph(sample,
|
||||||
|
CLISampleAttribute(),
|
||||||
|
seqs,
|
||||||
|
CLIDistStepMax(),
|
||||||
|
obioptions.CLIParallelWorkers())
|
||||||
|
if bar != nil {
|
||||||
|
bar.Add(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if CLISaveGraphToFiles() {
|
||||||
|
graph.WriteGmlFile(fmt.Sprintf("%s/%s.gml",
|
||||||
|
CLIGraphFilesDirectory(),
|
||||||
|
sample),
|
||||||
|
false, 1, 0, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
denoised := MinionDenoise(graph,
|
||||||
|
CLISampleAttribute(),
|
||||||
|
CLIKmerSize())
|
||||||
|
|
||||||
|
newIter.Push(obiiter.MakeBioSequenceBatch(sample_order, denoised))
|
||||||
|
|
||||||
|
sample_order++
|
||||||
|
}
|
||||||
|
|
||||||
|
newIter.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
newIter.WaitAndClose()
|
newIter.WaitAndClose()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
obiuniq.AddStatsOn(CLISampleAttribute())
|
||||||
order := 0
|
obiuniq.SetUniqueInMemory(false)
|
||||||
iterator = iterator.SortBatches()
|
obiuniq.SetNoSingleton(CLINoSingleton())
|
||||||
buffer := obiseq.MakeBioSequenceSlice()
|
return obiuniq.CLIUnique(newIter).Pipe(obiiter.WorkerPipe(obiannotate.AddSeqLengthWorker(), false))
|
||||||
|
|
||||||
for iterator.Next() {
|
|
||||||
seqs := iterator.Get()
|
|
||||||
|
|
||||||
sequences := seqs.Slice()
|
|
||||||
|
|
||||||
id := sequences[0].Source()
|
|
||||||
if id == "" {
|
|
||||||
id = sequences[0].Id()
|
|
||||||
}
|
|
||||||
consensus, err := BuildConsensus(sequences,
|
|
||||||
id,
|
|
||||||
CLIKmerSize(),
|
|
||||||
CLISaveGraphToFiles(),
|
|
||||||
CLIGraphFilesDirectory(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
buffer = append(buffer, consensus)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(buffer) == size {
|
|
||||||
newIter.Push(obiiter.MakeBioSequenceBatch(order, buffer))
|
|
||||||
order++
|
|
||||||
buffer = obiseq.MakeBioSequenceSlice()
|
|
||||||
}
|
|
||||||
seqs.Recycle(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(buffer) > 0 {
|
|
||||||
newIter.Push(obiiter.MakeBioSequenceBatch(order, buffer))
|
|
||||||
}
|
|
||||||
|
|
||||||
newIter.Done()
|
|
||||||
|
|
||||||
}()
|
|
||||||
|
|
||||||
return newIter
|
|
||||||
}
|
}
|
||||||
|
@ -5,29 +5,90 @@ import (
|
|||||||
"github.com/DavidGamba/go-getoptions"
|
"github.com/DavidGamba/go-getoptions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _saveGraph = "__@@NOSAVE@@__"
|
var _distStepMax = 1
|
||||||
|
var _sampleAttribute = "sample"
|
||||||
|
|
||||||
|
var _ratioMax = 1.0
|
||||||
|
|
||||||
|
var _clusterMode = false
|
||||||
|
var _onlyHead = false
|
||||||
|
|
||||||
var _kmerSize = -1
|
var _kmerSize = -1
|
||||||
|
|
||||||
func ObiconsensusOptionSet(options *getoptions.GetOpt) {
|
var _NoSingleton = false
|
||||||
|
|
||||||
|
var _saveGraph = "__@@NOSAVE@@__"
|
||||||
|
var _saveRatio = "__@@NOSAVE@@__"
|
||||||
|
|
||||||
|
// ObiminionOptionSet sets the options for obiminion.
|
||||||
|
//
|
||||||
|
// options: The options for configuring obiminion.
|
||||||
|
func ObiminionOptionSet(options *getoptions.GetOpt) {
|
||||||
|
options.StringVar(&_sampleAttribute, "sample", _sampleAttribute,
|
||||||
|
options.Alias("s"),
|
||||||
|
options.Description("Attribute containing sample descriptions (default %s)."))
|
||||||
|
|
||||||
|
options.IntVar(&_distStepMax, "distance", _distStepMax,
|
||||||
|
options.Alias("d"),
|
||||||
|
options.Description("Maximum numbers of differences between two variant sequences (default: %d)."))
|
||||||
|
|
||||||
options.StringVar(&_saveGraph, "save-graph", _saveGraph,
|
options.StringVar(&_saveGraph, "save-graph", _saveGraph,
|
||||||
options.Description("Creates a directory containing the set of De Bruijn graphs used by "+
|
options.Description("Creates a directory containing the set of DAG used by the obiclean clustering algorithm. "+
|
||||||
"the obiconsensus algorithm. "+
|
|
||||||
"The graph files follow the graphml format."),
|
"The graph files follow the graphml format."),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
options.StringVar(&_saveRatio, "save-ratio", _saveRatio,
|
||||||
|
options.Description("Creates a file containing the set of abundance ratio on the graph edge. "+
|
||||||
|
"The ratio file follows the csv format."),
|
||||||
|
)
|
||||||
options.IntVar(&_kmerSize, "kmer-size", _kmerSize,
|
options.IntVar(&_kmerSize, "kmer-size", _kmerSize,
|
||||||
options.ArgName("SIZE"),
|
options.ArgName("SIZE"),
|
||||||
options.Description("The size of the kmer used to build the consensus. "+
|
options.Description("The size of the kmer used to build the consensus. "+
|
||||||
"Default value = -1, which means that the kmer size is estimated from the data"),
|
"Default value = -1, which means that the kmer size is estimated from the data"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
options.BoolVar(&_NoSingleton, "no-singleton", _NoSingleton,
|
||||||
|
options.Description("If set, sequences occurring a single time in the data set are discarded."))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OptionSet sets up the options for the obiminion package.
|
||||||
|
//
|
||||||
|
// It takes a pointer to a getoptions.GetOpt object as a parameter.
|
||||||
|
// It does not return any value.
|
||||||
func OptionSet(options *getoptions.GetOpt) {
|
func OptionSet(options *getoptions.GetOpt) {
|
||||||
obiconvert.InputOptionSet(options)
|
obiconvert.InputOptionSet(options)
|
||||||
obiconvert.OutputOptionSet(options)
|
obiconvert.OutputOptionSet(options)
|
||||||
ObiconsensusOptionSet(options)
|
ObiminionOptionSet(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CLIDistStepMax returns the maximum distance between two sequences.
|
||||||
|
//
|
||||||
|
// The value of the distance is set by the user with the `-d` flag.
|
||||||
|
//
|
||||||
|
// No parameters.
|
||||||
|
// Returns an integer.
|
||||||
|
func CLIDistStepMax() int {
|
||||||
|
return _distStepMax
|
||||||
|
}
|
||||||
|
|
||||||
|
// CLISampleAttribute returns the name of the attribute used to store sample name.
|
||||||
|
//
|
||||||
|
// The value of the sample attribute is set by the user with the `-s` flag.
|
||||||
|
//
|
||||||
|
// No parameters.
|
||||||
|
// Returns a string.
|
||||||
|
func CLISampleAttribute() string {
|
||||||
|
return _sampleAttribute
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClusterMode() bool {
|
||||||
|
return _clusterMode
|
||||||
|
}
|
||||||
|
|
||||||
|
// `OnlyHead()` returns a boolean value that indicates whether the `-h` flag was passed to the program
|
||||||
|
func OnlyHead() bool {
|
||||||
|
return _onlyHead
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true it the obliclean graphs must be saved
|
// Returns true it the obliclean graphs must be saved
|
||||||
@ -40,6 +101,32 @@ func CLIGraphFilesDirectory() string {
|
|||||||
return _saveGraph
|
return _saveGraph
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true it the table of ratio must be saved
|
||||||
|
func IsSaveRatioTable() bool {
|
||||||
|
return _saveRatio != "__@@NOSAVE@@__"
|
||||||
|
}
|
||||||
|
|
||||||
|
// It returns the filename of the file that stores the ratio table
|
||||||
|
func RatioTableFilename() string {
|
||||||
|
return _saveRatio
|
||||||
|
}
|
||||||
|
|
||||||
|
// CLIKmerSize returns the value of the kmer size to use for building the consensus.
|
||||||
|
//
|
||||||
|
// The value of the kmer size is set by the user with the `-k` flag.
|
||||||
|
// The value -1 means that the kmer size is estimated as the minimum value that
|
||||||
|
// insure that no kmer are present more than one time in a sequence.
|
||||||
|
//
|
||||||
|
// No parameters.
|
||||||
|
// Returns an integer value.
|
||||||
func CLIKmerSize() int {
|
func CLIKmerSize() int {
|
||||||
return _kmerSize
|
return _kmerSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CLINoSingleton returns a boolean value indicating whether or not singleton sequences should be discarded.
|
||||||
|
//
|
||||||
|
// No parameters.
|
||||||
|
// Returns a boolean value indicating whether or not singleton sequences should be discarded.
|
||||||
|
func CLINoSingleton() bool {
|
||||||
|
return _NoSingleton
|
||||||
|
}
|
@ -1,280 +0,0 @@
|
|||||||
package obiminion
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obialign"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obigraph"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiiter"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obioptions"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiannotate"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiconsensus"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiconvert"
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiuniq"
|
|
||||||
"github.com/schollz/progressbar/v3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SampleWeight calculates the weight of a sample based on the statistics of a sequence.
|
|
||||||
//
|
|
||||||
// Parameters:
|
|
||||||
// - seqs: a pointer to BioSequenceSlice representing the sequences (*BioSequenceSlice)
|
|
||||||
// - sample: the sample for which the weight is calculated (string)
|
|
||||||
// - sample_key: the key used to access the sample's statistics (string)
|
|
||||||
// Return type: a function that takes an integer index and returns the weight of the sample at that index (func(int) int)
|
|
||||||
func SampleWeight(seqs *obiseq.BioSequenceSlice, sample, sample_key string) func(int) float64 {
|
|
||||||
|
|
||||||
f := func(i int) float64 {
|
|
||||||
|
|
||||||
stats := (*seqs)[i].StatsOn(sample_key, "NA")
|
|
||||||
|
|
||||||
if value, ok := stats[sample]; ok {
|
|
||||||
return float64(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
// SeqBySamples sorts the sequences by samples.
|
|
||||||
//
|
|
||||||
// Parameters:
|
|
||||||
// - seqs: a pointer to BioSequenceSlice representing the sequences (*BioSequenceSlice)
|
|
||||||
// - sample_key: a string representing the sample key (string)
|
|
||||||
//
|
|
||||||
// Return type:
|
|
||||||
// - map[string]BioSequenceSlice: a map indexed by sample names, each containing a slice of BioSequence objects (map[string]BioSequenceSlice)
|
|
||||||
func SeqBySamples(seqs obiseq.BioSequenceSlice, sample_key string) map[string]*obiseq.BioSequenceSlice {
|
|
||||||
|
|
||||||
samples := make(map[string]*obiseq.BioSequenceSlice)
|
|
||||||
|
|
||||||
for _, s := range seqs {
|
|
||||||
if s.HasStatsOn(sample_key) {
|
|
||||||
stats := s.StatsOn(sample_key, "NA")
|
|
||||||
for k := range stats {
|
|
||||||
if seqset, ok := samples[k]; ok {
|
|
||||||
*seqset = append(*seqset, s)
|
|
||||||
samples[k] = seqset
|
|
||||||
} else {
|
|
||||||
samples[k] = &obiseq.BioSequenceSlice{s}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if k, ok := s.GetStringAttribute(sample_key); ok {
|
|
||||||
if seqset, ok := samples[k]; ok {
|
|
||||||
*seqset = append(*seqset, s)
|
|
||||||
samples[k] = seqset
|
|
||||||
} else {
|
|
||||||
samples[k] = &obiseq.BioSequenceSlice{s}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return samples
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type Mutation struct {
|
|
||||||
Position int
|
|
||||||
SeqA byte
|
|
||||||
SeqB byte
|
|
||||||
Ratio float64
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuildDiffSeqGraph(name, name_key string,
|
|
||||||
seqs *obiseq.BioSequenceSlice,
|
|
||||||
distmax, nworkers int) *obigraph.Graph[*obiseq.BioSequence, Mutation] {
|
|
||||||
graph := obigraph.NewGraphBuffer[*obiseq.BioSequence, Mutation](name, (*[]*obiseq.BioSequence)(seqs))
|
|
||||||
iseq := make(chan int)
|
|
||||||
defer graph.Close()
|
|
||||||
|
|
||||||
ls := len(*seqs)
|
|
||||||
|
|
||||||
sw := SampleWeight(seqs, name, name_key)
|
|
||||||
graph.Graph.VertexWeight = sw
|
|
||||||
|
|
||||||
waiting := sync.WaitGroup{}
|
|
||||||
waiting.Add(nworkers)
|
|
||||||
|
|
||||||
bar := (*progressbar.ProgressBar)(nil)
|
|
||||||
if obiconvert.CLIProgressBar() {
|
|
||||||
|
|
||||||
pbopt := make([]progressbar.Option, 0, 5)
|
|
||||||
pbopt = append(pbopt,
|
|
||||||
progressbar.OptionSetWriter(os.Stderr),
|
|
||||||
progressbar.OptionSetWidth(15),
|
|
||||||
progressbar.OptionShowIts(),
|
|
||||||
progressbar.OptionSetPredictTime(true),
|
|
||||||
progressbar.OptionSetDescription(fmt.Sprintf("[Build graph] on %s", name)),
|
|
||||||
)
|
|
||||||
|
|
||||||
bar = progressbar.NewOptions(len(*seqs), pbopt...)
|
|
||||||
}
|
|
||||||
|
|
||||||
computeEdges := func() {
|
|
||||||
defer waiting.Done()
|
|
||||||
for i := range iseq {
|
|
||||||
s1 := (*seqs)[i]
|
|
||||||
for j := i + 1; j < ls; j++ {
|
|
||||||
s2 := (*seqs)[j]
|
|
||||||
ratio := sw(i) / sw(j)
|
|
||||||
ok, pos, a1, a2 := obialign.D1Or0(s1, s2)
|
|
||||||
if ok >= 0 {
|
|
||||||
graph.AddEdge(i, j, &Mutation{pos, a1, a2, ratio})
|
|
||||||
} else if distmax > 1 {
|
|
||||||
lcs, lali := obialign.FastLCSScore(s1, s2, distmax, nil)
|
|
||||||
dist := lali - lcs
|
|
||||||
if lcs > 0 && dist <= distmax {
|
|
||||||
// log.Infof("Seq %s and %s: LCSScore: %d, dist: %d\n", s1.Id(), s2.Id(), lcs, dist)
|
|
||||||
graph.AddEdge(i, j, &Mutation{pos, a1, a2, ratio})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if bar != nil {
|
|
||||||
bar.Add(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < nworkers; i++ {
|
|
||||||
go computeEdges()
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < ls; i++ {
|
|
||||||
iseq <- i
|
|
||||||
}
|
|
||||||
close(iseq)
|
|
||||||
|
|
||||||
waiting.Wait()
|
|
||||||
return graph.Graph
|
|
||||||
}
|
|
||||||
|
|
||||||
func MinionDenoise(graph *obigraph.Graph[*obiseq.BioSequence, Mutation],
|
|
||||||
sample_key string, kmer_size int) obiseq.BioSequenceSlice {
|
|
||||||
denoised := obiseq.MakeBioSequenceSlice(len(*graph.Vertices))
|
|
||||||
|
|
||||||
for i, v := range *graph.Vertices {
|
|
||||||
var err error
|
|
||||||
var clean *obiseq.BioSequence
|
|
||||||
degree := graph.Degree(i)
|
|
||||||
if degree > 4 {
|
|
||||||
pack := obiseq.MakeBioSequenceSlice(degree + 1)
|
|
||||||
for k,j := range graph.Neighbors(i) {
|
|
||||||
pack[k] = (*graph.Vertices)[j]
|
|
||||||
}
|
|
||||||
pack[degree] = v
|
|
||||||
clean, err = obiconsensus.BuildConsensus(pack,
|
|
||||||
fmt.Sprintf("%s_consensus", v.Id()),
|
|
||||||
kmer_size,
|
|
||||||
CLISaveGraphToFiles(), CLIGraphFilesDirectory())
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Warning(err)
|
|
||||||
clean = (*graph.Vertices)[i]
|
|
||||||
clean.SetAttribute("obiminion_consensus", false)
|
|
||||||
} else {
|
|
||||||
clean.SetAttribute("obiminion_consensus", true)
|
|
||||||
}
|
|
||||||
pack.Recycle(false)
|
|
||||||
} else {
|
|
||||||
clean = obiseq.NewBioSequence(v.Id(), v.Sequence(), v.Definition())
|
|
||||||
clean.SetAttribute("obiminion_consensus", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
clean.SetCount(int(graph.VertexWeight(i)))
|
|
||||||
clean.SetAttribute(sample_key, graph.Name)
|
|
||||||
|
|
||||||
denoised[i] = clean
|
|
||||||
}
|
|
||||||
|
|
||||||
return denoised
|
|
||||||
}
|
|
||||||
func CLIOBIMinion(itertator obiiter.IBioSequence) obiiter.IBioSequence {
|
|
||||||
dirname := CLIGraphFilesDirectory()
|
|
||||||
newIter := obiiter.MakeIBioSequence()
|
|
||||||
|
|
||||||
db := itertator.Load()
|
|
||||||
|
|
||||||
log.Infof("Sequence dataset of %d sequeences loaded\n", len(db))
|
|
||||||
|
|
||||||
samples := SeqBySamples(db, CLISampleAttribute())
|
|
||||||
db.Recycle(false)
|
|
||||||
|
|
||||||
log.Infof("Dataset composed of %d samples\n", len(samples))
|
|
||||||
|
|
||||||
if CLISaveGraphToFiles() {
|
|
||||||
if stat, err := os.Stat(dirname); err != nil || !stat.IsDir() {
|
|
||||||
// path does not exist or is not directory
|
|
||||||
os.RemoveAll(dirname)
|
|
||||||
err := os.Mkdir(dirname, 0755)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Cannot create directory %s for saving graphs", dirname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bar := (*progressbar.ProgressBar)(nil)
|
|
||||||
if obiconvert.CLIProgressBar() {
|
|
||||||
|
|
||||||
pbopt := make([]progressbar.Option, 0, 5)
|
|
||||||
pbopt = append(pbopt,
|
|
||||||
progressbar.OptionSetWriter(os.Stderr),
|
|
||||||
progressbar.OptionSetWidth(15),
|
|
||||||
progressbar.OptionShowIts(),
|
|
||||||
progressbar.OptionSetPredictTime(true),
|
|
||||||
progressbar.OptionSetDescription("[Filter graph on abundance ratio]"),
|
|
||||||
)
|
|
||||||
|
|
||||||
bar = progressbar.NewOptions(len(samples), pbopt...)
|
|
||||||
}
|
|
||||||
|
|
||||||
newIter.Add(1)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
sample_order := 0
|
|
||||||
for sample, seqs := range samples {
|
|
||||||
graph := BuildDiffSeqGraph(sample,
|
|
||||||
CLISampleAttribute(),
|
|
||||||
seqs,
|
|
||||||
CLIDistStepMax(),
|
|
||||||
obioptions.CLIParallelWorkers())
|
|
||||||
if bar != nil {
|
|
||||||
bar.Add(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if CLISaveGraphToFiles() {
|
|
||||||
graph.WriteGmlFile(fmt.Sprintf("%s/%s.gml",
|
|
||||||
CLIGraphFilesDirectory(),
|
|
||||||
sample),
|
|
||||||
false, 1, 0, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
denoised := MinionDenoise(graph,
|
|
||||||
CLISampleAttribute(),
|
|
||||||
CLIKmerSize())
|
|
||||||
|
|
||||||
newIter.Push(obiiter.MakeBioSequenceBatch(sample_order, denoised))
|
|
||||||
|
|
||||||
sample_order++
|
|
||||||
}
|
|
||||||
|
|
||||||
newIter.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
newIter.WaitAndClose()
|
|
||||||
}()
|
|
||||||
|
|
||||||
obiuniq.AddStatsOn(CLISampleAttribute())
|
|
||||||
obiuniq.SetUniqueInMemory(false)
|
|
||||||
obiuniq.SetNoSingleton(CLINoSingleton())
|
|
||||||
return obiuniq.CLIUnique(newIter).Pipe(obiiter.WorkerPipe(obiannotate.AddSeqLengthWorker(), false))
|
|
||||||
}
|
|
@ -1,132 +0,0 @@
|
|||||||
package obiminion
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiconvert"
|
|
||||||
"github.com/DavidGamba/go-getoptions"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _distStepMax = 1
|
|
||||||
var _sampleAttribute = "sample"
|
|
||||||
|
|
||||||
var _ratioMax = 1.0
|
|
||||||
|
|
||||||
var _clusterMode = false
|
|
||||||
var _onlyHead = false
|
|
||||||
|
|
||||||
var _kmerSize = -1
|
|
||||||
|
|
||||||
var _NoSingleton = false
|
|
||||||
|
|
||||||
var _saveGraph = "__@@NOSAVE@@__"
|
|
||||||
var _saveRatio = "__@@NOSAVE@@__"
|
|
||||||
|
|
||||||
// ObiminionOptionSet sets the options for obiminion.
|
|
||||||
//
|
|
||||||
// options: The options for configuring obiminion.
|
|
||||||
func ObiminionOptionSet(options *getoptions.GetOpt) {
|
|
||||||
options.StringVar(&_sampleAttribute, "sample", _sampleAttribute,
|
|
||||||
options.Alias("s"),
|
|
||||||
options.Description("Attribute containing sample descriptions (default %s)."))
|
|
||||||
|
|
||||||
options.IntVar(&_distStepMax, "distance", _distStepMax,
|
|
||||||
options.Alias("d"),
|
|
||||||
options.Description("Maximum numbers of differences between two variant sequences (default: %d)."))
|
|
||||||
|
|
||||||
options.StringVar(&_saveGraph, "save-graph", _saveGraph,
|
|
||||||
options.Description("Creates a directory containing the set of DAG used by the obiclean clustering algorithm. "+
|
|
||||||
"The graph files follow the graphml format."),
|
|
||||||
)
|
|
||||||
|
|
||||||
options.StringVar(&_saveRatio, "save-ratio", _saveRatio,
|
|
||||||
options.Description("Creates a file containing the set of abundance ratio on the graph edge. "+
|
|
||||||
"The ratio file follows the csv format."),
|
|
||||||
)
|
|
||||||
options.IntVar(&_kmerSize, "kmer-size", _kmerSize,
|
|
||||||
options.ArgName("SIZE"),
|
|
||||||
options.Description("The size of the kmer used to build the consensus. "+
|
|
||||||
"Default value = -1, which means that the kmer size is estimated from the data"),
|
|
||||||
)
|
|
||||||
|
|
||||||
options.BoolVar(&_NoSingleton, "no-singleton", _NoSingleton,
|
|
||||||
options.Description("If set, sequences occurring a single time in the data set are discarded."))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// OptionSet sets up the options for the obiminion package.
|
|
||||||
//
|
|
||||||
// It takes a pointer to a getoptions.GetOpt object as a parameter.
|
|
||||||
// It does not return any value.
|
|
||||||
func OptionSet(options *getoptions.GetOpt) {
|
|
||||||
obiconvert.InputOptionSet(options)
|
|
||||||
obiconvert.OutputOptionSet(options)
|
|
||||||
ObiminionOptionSet(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CLIDistStepMax returns the maximum distance between two sequences.
|
|
||||||
//
|
|
||||||
// The value of the distance is set by the user with the `-d` flag.
|
|
||||||
//
|
|
||||||
// No parameters.
|
|
||||||
// Returns an integer.
|
|
||||||
func CLIDistStepMax() int {
|
|
||||||
return _distStepMax
|
|
||||||
}
|
|
||||||
|
|
||||||
// CLISampleAttribute returns the name of the attribute used to store sample name.
|
|
||||||
//
|
|
||||||
// The value of the sample attribute is set by the user with the `-s` flag.
|
|
||||||
//
|
|
||||||
// No parameters.
|
|
||||||
// Returns a string.
|
|
||||||
func CLISampleAttribute() string {
|
|
||||||
return _sampleAttribute
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClusterMode() bool {
|
|
||||||
return _clusterMode
|
|
||||||
}
|
|
||||||
|
|
||||||
// `OnlyHead()` returns a boolean value that indicates whether the `-h` flag was passed to the program
|
|
||||||
func OnlyHead() bool {
|
|
||||||
return _onlyHead
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true it the obliclean graphs must be saved
|
|
||||||
func CLISaveGraphToFiles() bool {
|
|
||||||
return _saveGraph != "__@@NOSAVE@@__"
|
|
||||||
}
|
|
||||||
|
|
||||||
// It returns the directory where the graph files are saved
|
|
||||||
func CLIGraphFilesDirectory() string {
|
|
||||||
return _saveGraph
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true it the table of ratio must be saved
|
|
||||||
func IsSaveRatioTable() bool {
|
|
||||||
return _saveRatio != "__@@NOSAVE@@__"
|
|
||||||
}
|
|
||||||
|
|
||||||
// It returns the filename of the file that stores the ratio table
|
|
||||||
func RatioTableFilename() string {
|
|
||||||
return _saveRatio
|
|
||||||
}
|
|
||||||
|
|
||||||
// CLIKmerSize returns the value of the kmer size to use for building the consensus.
|
|
||||||
//
|
|
||||||
// The value of the kmer size is set by the user with the `-k` flag.
|
|
||||||
// The value -1 means that the kmer size is estimated as the minimum value that
|
|
||||||
// insure that no kmer are present more than one time in a sequence.
|
|
||||||
//
|
|
||||||
// No parameters.
|
|
||||||
// Returns an integer value.
|
|
||||||
func CLIKmerSize() int {
|
|
||||||
return _kmerSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// CLINoSingleton returns a boolean value indicating whether or not singleton sequences should be discarded.
|
|
||||||
//
|
|
||||||
// No parameters.
|
|
||||||
// Returns a boolean value indicating whether or not singleton sequences should be discarded.
|
|
||||||
func CLINoSingleton() bool {
|
|
||||||
return _NoSingleton
|
|
||||||
}
|
|
Reference in New Issue
Block a user