Browse files

Use nil for undefined Score and Probability fields

  • Loading branch information...
1 parent a4d7bff commit 9f0663f009ad692165c6f57c9bb756ce2537c094 @kortschak kortschak committed Apr 3, 2012
Showing with 37 additions and 28 deletions.
  1. +2 −2 feat/feat.go
  2. +6 −3 io/featio/bed/bed.go
  3. +9 −6 io/featio/bed/bed_test.go
  4. +7 −5 io/featio/gff/gff.go
  5. +13 −12 io/featio/gff/gff_test.go
View
4 feat/feat.go
@@ -34,8 +34,8 @@ type Feature struct {
Start int
End int
Feature string
- Score float64
- Probability float64
+ Score *float64
+ Probability *float64
Attributes string
Comments string
Frame int8
View
9 io/featio/bed/bed.go
@@ -117,8 +117,11 @@ func (self *Reader) Read() (f *feat.Feature, err error) {
case nameField:
f.ID = elems[i]
case scoreField:
- if f.Score, se = strconv.ParseFloat(elems[i], 64); se != nil {
- f.Score = 0
+ if f.Score == nil {
+ f.Score = new(float64)
+ }
+ if *f.Score, se = strconv.ParseFloat(elems[i], 64); se != nil {
+ *f.Score = 0
}
case strandField:
if f.Strand, ok = CharToStrand[elems[i]]; !ok {
@@ -209,7 +212,7 @@ func (self *Writer) Stringify(f *feat.Feature) string {
fields[strandField] = StrandToChar[f.Strand]
fallthrough
case 5:
- fields[scoreField] = strconv.FormatFloat(f.Score, self.FloatFormat, self.Precision, 64)
+ fields[scoreField] = strconv.FormatFloat(*f.Score, self.FloatFormat, self.Precision, 64)
fallthrough
case 4:
fields[nameField] = f.ID
View
15 io/featio/bed/bed_test.go
@@ -41,6 +41,9 @@ var (
}
)
+// Helpers
+func floatPtr(f float64) *float64 { return &f }
+
// Tests
func Test(t *testing.T) { check.TestingT(t) }
@@ -51,19 +54,19 @@ var _ = check.Suite(&S{})
var (
expect [][]feat.Feature = [][]feat.Feature{
{
- {ID: "chr1:11873..14409", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: 0, Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0, Meta: interface{}(nil)},
+ {ID: "chr1:11873..14409", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: nil, Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0, Meta: interface{}(nil)},
},
{
- {ID: "uc001aaa.3", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: 0, Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0, Meta: interface{}(nil)},
+ {ID: "uc001aaa.3", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: nil, Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0, Meta: interface{}(nil)},
},
{
- {ID: "uc001aaa.3", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: 3, Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0, Meta: interface{}(nil)},
+ {ID: "uc001aaa.3", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: floatPtr(3), Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0, Meta: interface{}(nil)},
},
{
- {ID: "uc001aaa.3", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: 3, Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 1, Moltype: 0, Meta: interface{}(nil)},
+ {ID: "uc001aaa.3", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: floatPtr(3), Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: 1, Moltype: 0, Meta: interface{}(nil)},
},
{
- {ID: "uc001aaa.3", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: 3, Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 1, Moltype: 0, Meta: interface{}(nil)},
+ {ID: "uc001aaa.3", Source: "", Location: "chr1", Start: 11873, End: 14409, Feature: "", Score: floatPtr(3), Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: 1, Moltype: 0, Meta: interface{}(nil)},
},
}
)
@@ -91,7 +94,7 @@ func (s *S) TestReadBed(c *check.C) {
}
if len(obtain) == len(expect[k]) {
for j := range obtain {
- c.Check(*obtain[j], check.Equals, expect[k][j])
+ c.Check(*obtain[j], check.DeepEquals, expect[k][j])
}
} else {
c.Log(k, b)
View
12 io/featio/gff/gff.go
@@ -25,7 +25,6 @@ import (
"github.com/kortschak/biogo/io/seqio/fasta"
"github.com/kortschak/biogo/seq"
"io"
- "math"
"os"
"strconv"
"strings"
@@ -238,8 +237,11 @@ func (self *Reader) Read() (f *feat.Feature, err error) {
}
score, se := strconv.ParseFloat(elems[scoreField], 64)
+ var scorePtr *float64
if se != nil {
- score = math.NaN()
+ scorePtr = nil
+ } else {
+ scorePtr = &score
}
f = &feat.Feature{
@@ -249,7 +251,7 @@ func (self *Reader) Read() (f *feat.Feature, err error) {
Start: startPos,
End: endPos,
Feature: elems[featureField],
- Score: score,
+ Score: scorePtr,
Frame: int8(fr),
Strand: s,
Moltype: self.Type, // currently we default to bio.DNA
@@ -344,8 +346,8 @@ func (self *Writer) Stringify(f *feat.Feature) string {
strconv.Itoa(f.End),
})
- if !math.IsNaN(f.Score) {
- fields[scoreField] = strconv.FormatFloat(f.Score, self.FloatFormat, self.Precision, 64)
+ if f.Score != nil {
+ fields[scoreField] = strconv.FormatFloat(*f.Score, self.FloatFormat, self.Precision, 64)
} else {
fields[scoreField] = "."
}
View
25 io/featio/gff/gff_test.go
@@ -16,14 +16,12 @@ package gff
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import (
- "fmt"
"github.com/kortschak/biogo/bio"
"github.com/kortschak/biogo/feat"
"github.com/kortschak/biogo/seq"
"io"
"io/ioutil"
check "launchpad.net/gocheck"
- "math"
"os"
"testing"
)
@@ -35,6 +33,9 @@ var (
}
)
+// Helpers
+func floatPtr(f float64) *float64 { return &f }
+
// Tests
func Test(t *testing.T) { check.TestingT(t) }
@@ -44,19 +45,19 @@ var _ = check.Suite(&S{})
var (
expect []feat.Feature = []feat.Feature{
- {ID: "SEQ1:102..105", Source: "EMBL", Location: "SEQ1", Start: 102, End: 105, Feature: "atg", Score: math.NaN(), Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
- {ID: "SEQ1:102..172", Source: "EMBL", Location: "SEQ1", Start: 102, End: 172, Feature: "exon", Score: math.NaN(), Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
- {ID: "SEQ1:171..173", Source: "EMBL", Location: "SEQ1", Start: 171, End: 173, Feature: "splice5", Score: math.NaN(), Probability: 0, Attributes: "", Comments: "", Frame: -1, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
- {ID: "SEQ1:171..173", Source: "netgene", Location: "SEQ1", Start: 171, End: 173, Feature: "splice5", Score: 0.94, Probability: 0, Attributes: "", Comments: "", Frame: -1, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
- {ID: "SEQ1:162..182", Source: "genie", Location: "SEQ1", Start: 162, End: 182, Feature: "sp5-20", Score: 2.3, Probability: 0, Attributes: "", Comments: "", Frame: -1, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
- {ID: "SEQ1:167..177", Source: "genie", Location: "SEQ1", Start: 167, End: 177, Feature: "sp5-10", Score: 2.1, Probability: 0, Attributes: "", Comments: "", Frame: -1, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
- {ID: "SEQ2:16..19", Source: "grail", Location: "SEQ2", Start: 16, End: 19, Feature: "ATG", Score: 2.1, Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: -1, Moltype: 0x0, Meta: interface{}(nil)},
+ {ID: "SEQ1:102..105", Source: "EMBL", Location: "SEQ1", Start: 102, End: 105, Feature: "atg", Score: nil, Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
+ {ID: "SEQ1:102..172", Source: "EMBL", Location: "SEQ1", Start: 102, End: 172, Feature: "exon", Score: nil, Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
+ {ID: "SEQ1:171..173", Source: "EMBL", Location: "SEQ1", Start: 171, End: 173, Feature: "splice5", Score: nil, Probability: nil, Attributes: "", Comments: "", Frame: -1, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
+ {ID: "SEQ1:171..173", Source: "netgene", Location: "SEQ1", Start: 171, End: 173, Feature: "splice5", Score: floatPtr(0.94), Probability: nil, Attributes: "", Comments: "", Frame: -1, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
+ {ID: "SEQ1:162..182", Source: "genie", Location: "SEQ1", Start: 162, End: 182, Feature: "sp5-20", Score: floatPtr(2.3), Probability: nil, Attributes: "", Comments: "", Frame: -1, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
+ {ID: "SEQ1:167..177", Source: "genie", Location: "SEQ1", Start: 167, End: 177, Feature: "sp5-10", Score: floatPtr(2.1), Probability: nil, Attributes: "", Comments: "", Frame: -1, Strand: 1, Moltype: 0x0, Meta: interface{}(nil)},
+ {ID: "SEQ2:16..19", Source: "grail", Location: "SEQ2", Start: 16, End: 19, Feature: "ATG", Score: floatPtr(2.1), Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: -1, Moltype: 0x0, Meta: interface{}(nil)},
}
expectMeta []interface{} = []interface{}{
&seq.Seq{ID: "<seqname>", Seq: []byte("acggctcggattggcgctggatgatagatcagacgac..."), Offset: 0, Strand: 1, Circular: false, Moltype: 0x0, Quality: (*seq.Quality)(nil), Inplace: false, Meta: interface{}(nil)},
&seq.Seq{ID: "<seqname>", Seq: []byte("acggcucggauuggcgcuggaugauagaucagacgac..."), Offset: 0, Strand: 1, Circular: false, Moltype: 0x1, Quality: (*seq.Quality)(nil), Inplace: false, Meta: interface{}(nil)},
&seq.Seq{ID: "<seqname>", Seq: []byte("MVLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSF..."), Offset: 0, Strand: 1, Circular: false, Moltype: 0x2, Quality: (*seq.Quality)(nil), Inplace: false, Meta: interface{}(nil)},
- &feat.Feature{ID: "<seqname>", Source: "", Location: "", Start: 0, End: 5, Feature: "", Score: 0, Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0x0, Meta: interface{}(nil)},
+ &feat.Feature{ID: "<seqname>", Source: "", Location: "", Start: 0, End: 5, Feature: "", Score: nil, Probability: nil, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0x0, Meta: interface{}(nil)},
}
writeMeta []interface{} = []interface{}{
"gff-version 2",
@@ -66,7 +67,7 @@ var (
&seq.Seq{ID: "<seqname>", Seq: []byte("acggctcggattggcgctggatgatagatcagacgac..."), Offset: 0, Strand: 1, Circular: false, Moltype: 0x0, Quality: (*seq.Quality)(nil), Inplace: false, Meta: interface{}(nil)},
&seq.Seq{ID: "<seqname>", Seq: []byte("acggcucggauuggcgcuggaugauagaucagacgac..."), Offset: 0, Strand: 1, Circular: false, Moltype: 0x1, Quality: (*seq.Quality)(nil), Inplace: false, Meta: interface{}(nil)},
&seq.Seq{ID: "<seqname>", Seq: []byte("MVLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSF..."), Offset: 0, Strand: 1, Circular: false, Moltype: 0x2, Quality: (*seq.Quality)(nil), Inplace: false, Meta: interface{}(nil)},
- &feat.Feature{ID: "<seqname>", Source: "", Location: "", Start: 0, End: 5, Feature: "", Score: 0, Probability: 0, Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0x0, Meta: interface{}(nil)},
+ &feat.Feature{ID: "<seqname>", Source: "", Location: "", Start: 0, End: 5, Feature: "", Score: floatPtr(0), Probability: floatPtr(0), Attributes: "", Comments: "", Frame: 0, Strand: 0, Moltype: 0x0, Meta: interface{}(nil)},
}
)
@@ -92,7 +93,7 @@ func (s *S) TestReadGFF(c *check.C) {
}
if len(obtain) == len(expect) {
for j := range obtain {
- c.Check(fmt.Sprintf("%#v", *obtain[j]), check.Equals, fmt.Sprintf("%#v", expect[j]))
+ c.Check(*obtain[j], check.DeepEquals, expect[j])
}
} else {
c.Check(len(obtain), check.Equals, len(expect))

0 comments on commit 9f0663f

Please sign in to comment.