Change the API of workers

Former-commit-id: 9b07306edd8cf28266f86f95823948fa99d39ea9
This commit is contained in:
2024-03-02 16:03:46 -04:00
parent 4a0b20484f
commit 0f3871d203
19 changed files with 194 additions and 120 deletions

View File

@ -28,16 +28,18 @@ func Expression(expression string) func(*BioSequence) (interface{}, error) {
func EditIdWorker(expression string) SeqWorker {
e := Expression(expression)
f := func(sequence *BioSequence) *BioSequence {
f := func(sequence *BioSequence) (BioSequenceSlice, error) {
v, err := e(sequence)
if err != nil {
log.Fatalf("Expression '%s' cannot be evaluated on sequence %s",
if err == nil {
sequence.SetId(fmt.Sprintf("%v", v))
} else {
err = fmt.Errorf("Expression '%s' cannot be evaluated on sequence %s : %v",
expression,
sequence.Id())
sequence.Id(),
err)
}
sequence.SetId(fmt.Sprintf("%v", v))
return sequence
return BioSequenceSlice{sequence}, err
}
return f
@ -45,16 +47,18 @@ func EditIdWorker(expression string) SeqWorker {
func EditAttributeWorker(key string, expression string) SeqWorker {
e := Expression(expression)
f := func(sequence *BioSequence) *BioSequence {
f := func(sequence *BioSequence) (BioSequenceSlice, error) {
v, err := e(sequence)
if err != nil {
log.Fatalf("Expression '%s' cannot be evaluated on sequence %s",
if err == nil {
sequence.SetAttribute(key, v)
} else {
err = fmt.Errorf("Expression '%s' cannot be evaluated on sequence %s : %v",
expression,
sequence.Id())
sequence.Id(),
err)
}
sequence.SetAttribute(key, v)
return sequence
return BioSequenceSlice{sequence}, err
}
return f

View File

@ -105,8 +105,8 @@ func (sequence *BioSequence) _revcmpMutation() *BioSequence {
* @returns {SeqWorker} A function that accepts *BioSequence and returns its reversed-complement form.
*/
func ReverseComplementWorker(inplace bool) SeqWorker {
f := func(input *BioSequence) *BioSequence {
return input.ReverseComplement(inplace)
f := func(input *BioSequence) (BioSequenceSlice, error) {
return BioSequenceSlice{input.ReverseComplement(inplace)}, nil
}
return f

View File

@ -1,20 +1,25 @@
package obiseq
import log "github.com/sirupsen/logrus"
import (
"fmt"
"slices"
log "github.com/sirupsen/logrus"
)
type SeqAnnotator func(*BioSequence)
type SeqWorker func(*BioSequence) *BioSequence
type SeqSliceWorker func(BioSequenceSlice) BioSequenceSlice
type SeqWorker func(*BioSequence) (BioSequenceSlice, error)
type SeqSliceWorker func(BioSequenceSlice) (BioSequenceSlice, error)
func NilSeqWorker(seq *BioSequence) *BioSequence {
return seq
func NilSeqWorker(seq *BioSequence) (BioSequenceSlice, error) {
return BioSequenceSlice{seq}, nil
}
func AnnotatorToSeqWorker(function SeqAnnotator) SeqWorker {
f := func(seq *BioSequence) *BioSequence {
f := func(seq *BioSequence) (BioSequenceSlice, error) {
function(seq)
return seq
return BioSequenceSlice{seq}, nil
}
return f
}
@ -25,35 +30,47 @@ func SeqToSliceWorker(worker SeqWorker,
if worker == nil {
if inplace {
f = func(input BioSequenceSlice) BioSequenceSlice {
return input
f = func(input BioSequenceSlice) (BioSequenceSlice, error) {
return input, nil
}
} else {
f = func(input BioSequenceSlice) BioSequenceSlice {
f = func(input BioSequenceSlice) (BioSequenceSlice, error) {
output := MakeBioSequenceSlice(len(input))
copy(output, input)
return output
return output, nil
}
}
} else {
f = func(input BioSequenceSlice) BioSequenceSlice {
f = func(input BioSequenceSlice) (BioSequenceSlice, error) {
output := input
if !inplace {
output = MakeBioSequenceSlice(len(input))
}
i := 0
for _, s := range input {
r := worker(s)
if r != nil {
output[i] = r
i++
} else if breakOnError {
log.Fatalf("got an error on sequence %s processing",
r.Id())
r, err := worker(s)
if err == nil {
for _, rs := range r {
output[i] = rs
i++
if i == cap(output) {
slices.Grow(output, cap(output))
}
}
} else {
if breakOnError {
err = fmt.Errorf("got an error on sequence %s processing : %v",
s.Id(), err)
return BioSequenceSlice{}, err
} else {
log.Warnf("got an error on sequence %s processing",
s.Id())
}
}
}
return output[0:i]
return output[0:i], nil
}
}
@ -61,15 +78,16 @@ func SeqToSliceWorker(worker SeqWorker,
return f
}
func SeqToSliceConditionalWorker(worker SeqWorker,
func SeqToSliceConditionalWorker(
condition SequencePredicate,
worker SeqWorker,
inplace, breakOnError bool) SeqSliceWorker {
if condition == nil {
return SeqToSliceWorker(worker, inplace, breakOnError)
}
f := func(input BioSequenceSlice) BioSequenceSlice {
f := func(input BioSequenceSlice) (BioSequenceSlice, error) {
output := input
if !inplace {
output = MakeBioSequenceSlice(len(input))
@ -79,18 +97,29 @@ func SeqToSliceConditionalWorker(worker SeqWorker,
for _, s := range input {
if condition(s) {
r := worker(s)
if r != nil {
output[i] = r
i++
} else if breakOnError {
log.Fatalf("got an error on sequence %s processing",
r.Id())
r, err := worker(s)
if err == nil {
for _, rs := range r {
output[i] = rs
i++
if i == cap(output) {
slices.Grow(output, cap(output))
}
}
} else {
if breakOnError {
err = fmt.Errorf("got an error on sequence %s processing : %v",
s.Id(), err)
return BioSequenceSlice{}, err
} else {
log.Warnf("got an error on sequence %s processing",
s.Id())
}
}
}
}
return output[0:i]
return output[0:i], nil
}
return f
@ -105,11 +134,17 @@ func (worker SeqWorker) ChainWorkers(next SeqWorker) SeqWorker {
}
}
f := func(seq *BioSequence) *BioSequence {
sw := SeqToSliceWorker(next, true, false)
f := func(seq *BioSequence) (BioSequenceSlice, error) {
if seq == nil {
return nil
return BioSequenceSlice{}, nil
}
return next(worker(seq))
slice, err := worker(seq)
if err == nil {
slice, err = sw(slice)
}
return slice, err
}
return f