Repository: Koeng101/dnadesign (language: python)

Issue:
Remove gff
Gff is kinda a [bad format](https://blastedbio.blogspot.com/2011/08/why-are-ncbi-gff3-files-still-broken.html) , and I don't want to maintain the parser, so it should be removed. Use genbank.


Discussion / hints:

Fix patch:
diff --git a/lib/bio/gff/gff.go b/lib/bio/gff/gff.go
deleted file mode 100644
index 0abd002..0000000
--- a/lib/bio/gff/gff.go
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
-Package gff provides gff parsers and writers.
-
-GFF stands for "general feature format". It is an alternative to GenBank for
-storing data about genomic sequences. While not often used in synthetic biology
-research, it is more commonly used in bioinformatics for digesting features of
-genomic sequences.
-
-This package provides a parser and writer to convert between the gff file
-format and the more general poly.Sequence struct.
-*/
-package gff
-
-import (
-	"bytes"
-	"errors"
-	"io"
-	"os"
-	"sort"
-	"strconv"
-	"strings"
-
-	"lukechampine.com/blake3"
-
-	"github.com/koeng101/dnadesign/lib/transform"
-)
-
-var (
-	readAllFn = io.ReadAll
-	atoiFn    = strconv.Atoi
-	openFn    = os.Open
-)
-
-// Gff is a struct that represents a gff file.
-type Gff struct {
-	Meta     Meta
-	Features []Feature // will need a GetFeatures interface to standardize
-	Sequence string
-}
-
-// Meta holds meta information about a gff file.
-type Meta struct {
-	Name                 string   `json:"name"`
-	Description          string   `json:"description"`
-	Version              string   `json:"gff_version"`
-	RegionStart          int      `json:"region_start"`
-	RegionEnd            int      `json:"region_end"`
-	Size                 int      `json:"size"`
-	SequenceHash         string   `json:"sequence_hash"`
-	SequenceHashFunction string   `json:"hash_function"`
-	CheckSum             [32]byte `json:"checkSum"` // blake3 checksum of the parsed file itself. Useful for if you want to check if incoming genbank/gff files are different.
-}
-
-// Feature is a struct that represents a feature in a gff file.
-type Feature struct {
-	Name           string            `json:"name"`
-	Source         string            `json:"source"`
-	Type           string            `json:"type"`
-	Score          string            `json:"score"`
-	Strand         string            `json:"strand"`
-	Phase          string            `json:"phase"`
-	Attributes     map[string]string `json:"attributes"`
-	Location       Location          `json:"location"`
-	ParentSequence *Gff              `json:"-"`
-}
-
-// Location is a struct that represents a location in a gff file.
-type Location struct {
-	Start             int        `json:"start"`
-	End               int        `json:"end"`
-	Complement        bool       `json:"complement"`
-	Join              bool       `json:"join"`
-	FivePrimePartial  bool       `json:"five_prime_partial"`
-	ThreePrimePartial bool       `json:"three_prime_partial"`
-	SubLocations      []Location `json:"sub_locations"`
-}
-
-// AddFeature takes a feature and adds it to the Gff struct.
-func (sequence *Gff) AddFeature(feature *Feature) error {
-	feature.ParentSequence = sequence
-	featureCopy := *feature
-	sequence.Features = append(sequence.Features, featureCopy)
-	return nil
-}
-
-// GetSequence takes a feature and returns a sequence string for that feature.
-func (feature Feature) GetSequence() (string, error) {
-	return getFeatureSequence(feature, feature.Location)
-}
-
-// getFeatureSequence takes a feature and location object and returns a sequence string.
-func getFeatureSequence(feature Feature, location Location) (string, error) {
-	var sequenceBuffer bytes.Buffer
-	var sequenceString string
-	parentSequence := feature.ParentSequence.Sequence
-
-	if len(location.SubLocations) == 0 {
-		sequenceBuffer.WriteString(parentSequence[location.Start:location.End])
-	} else {
-		for _, subLocation := range location.SubLocations {
-			sequence, _ := getFeatureSequence(feature, subLocation)
-			sequenceBuffer.WriteString(sequence)
-		}
-	}
-
-	// reverse complements resulting string if needed.
-	if location.Complement {
-		sequenceString = transform.ReverseComplement(sequenceBuffer.String())
-	} else {
-		sequenceString = sequenceBuffer.String()
-	}
-
-	return sequenceString, nil
-}
-
-// Parse Takes in a string representing a gffv3 file and parses it into an Sequence object.
-func Parse(file io.Reader) (Gff, error) {
-	fileBytes, err := readAllFn(file)
-	if err != nil {
-		return Gff{}, err
-	}
-
-	gffString := string(fileBytes)
-	gff := Gff{}
-
-	// Add the CheckSum to sequence (blake3)
-	gff.Meta.CheckSum = blake3.Sum256(fileBytes)
-
-	lines := strings.Split(gffString, "\n")
-	regionStringArray, endOfMetaInfo, err := extractInfoFromField(lines, "##sequence-region")
-	metaString := lines[0:endOfMetaInfo]
-	versionString := metaString[0]
-	if err != nil {
-		return Gff{}, err
-	}
-	// get name for general meta
-	meta := Meta{}
-	meta.Name = regionStringArray[1] // Formally region name, but changed to name here for generality/interoperability.
-
-	// get meta info only specific to GFF files
-	meta.Version = strings.Split(versionString, " ")[1]
-	meta.RegionStart, err = atoiFn(regionStringArray[2])
-	if err != nil {
-		return Gff{}, err
-	}
-	meta.RegionEnd, err = atoiFn(regionStringArray[3])
-	if err != nil {
-		return Gff{}, err
-	}
-	meta.Size = meta.RegionEnd - meta.RegionStart
-
-	var sequenceBuffer bytes.Buffer
-	fastaFlag := false
-	for _, line := range lines {
-		if line == "##FASTA" {
-			fastaFlag = true
-		} else if len(line) == 0 {
-			continue
-		} else if line[0:2] == "##" || line[0:2] == "#!" {
-			continue
-		} else if fastaFlag && line[0:1] != ">" {
-			// sequence.Sequence = sequence.Sequence + line
-			sequenceBuffer.WriteString(line)
-		} else if fastaFlag && line[0:1] == ">" {
-			gff.Meta.Description = line
-		} else {
-			record := Feature{}
-			fields := strings.Split(line, "\t")
-			record.Name = fields[0]
-			record.Source = fields[1]
-			record.Type = fields[2]
-
-			// Indexing starts at 1 for gff so we need to shift down for Sequence 0 index.
-			record.Location.Start, err = atoiFn(fields[3])
-			if err != nil {
-				return Gff{}, err
-			}
-
-			record.Location.Start--
-			record.Location.End, err = atoiFn(fields[4])
-			if err != nil {
-				return Gff{}, err
-			}
-
-			record.Score = fields[5]
-			record.Strand = fields[6]
-			record.Phase = fields[7]
-			record.Attributes = make(map[string]string)
-			attributes := fields[8]
-			// var eqIndex int
-			attributeSlice := strings.Split(attributes, ";")
-
-			for _, attribute := range attributeSlice {
-				attributeSplit := strings.Split(attribute, "=")
-				key := attributeSplit[0]
-				value := attributeSplit[1]
-				record.Attributes[key] = value
-			}
-			err = gff.AddFeature(&record)
-			if err != nil {
-				return Gff{}, err
-			}
-		}
-	}
-	gff.Sequence = sequenceBuffer.String()
-	gff.Meta = meta
-
-	return gff, err
-}
-
-// regionString takes in the lines array,fieldName that is needed in gff file, and
-// returns the region containing fieldName if found
-// throws error if not found
-func extractInfoFromField(lines []string, fieldName string) ([]string, int, error) {
-	index := 0
-	endOfMetaInfo := 0
-	for lineIndex, line := range lines {
-		if strings.Contains(line, "#") {
-			if strings.Contains(line, fieldName) {
-				index = lineIndex
-			}
-			continue
-		}
-		endOfMetaInfo = lineIndex
-		break
-	}
-	if index == 0 && fieldName != "gff-version" {
-		return nil, 0, errors.New("the given file does not have any meta information")
-	}
-	return strings.Split(lines[index], " "), endOfMetaInfo, nil
-}
-
-// Build takes an Annotated sequence and returns a byte array representing a gff to be written out.
-func Build(sequence Gff) ([]byte, error) {
-	var gffBuffer bytes.Buffer
-
-	versionString := "##gff-version 3 \n"
-	if sequence.Meta.Version != "" {
-		versionString = "##gff-version " + sequence.Meta.Version + "\n"
-	}
-
-	gffBuffer.WriteString(versionString)
-
-	name := "Sequence"
-	start := "1"
-	end := strconv.Itoa(sequence.Meta.RegionEnd)
-
-	if sequence.Meta.Name != "" {
-		name = sequence.Meta.Name
-	}
-
-	if sequence.Meta.RegionStart != 0 {
-		start = strconv.Itoa(sequence.Meta.RegionStart)
-	}
-
-	regionString := "##sequence-region " + name + " " + start + " " + end + "\n"
-	gffBuffer.WriteString(regionString)
-
-	for _, feature := range sequence.Features {
-		var featureString string
-
-		featureSource := "feature"
-		if feature.Source != "" {
-			featureSource = feature.Source
-		}
-
-		featureType := "unknown"
-		if feature.Type != "" {
-			featureType = feature.Type
-		}
-
-		// Indexing starts at 1 for gff so we need to shift up from Sequence 0 index.
-		featureStart := strconv.Itoa(feature.Location.Start + 1)
-		featureEnd := strconv.Itoa(feature.Location.End)
-
-		featureScore := feature.Score
-		featureStrand := feature.Strand
-		featurePhase := feature.Phase
-		var featureAttributes string
-
-		keys := make([]string, 0, len(feature.Attributes))
-		for key := range feature.Attributes {
-			keys = append(keys, key)
-		}
-		sort.Strings(keys)
-
-		for _, key := range keys {
-			attributeString := key + "=" + feature.Attributes[key] + ";"
-			featureAttributes += attributeString
-		}
-
-		if len(featureAttributes) > 0 {
-			featureAttributes = featureAttributes[0 : len(featureAttributes)-1]
-		}
-		TAB := "\t"
-		featureString = feature.Name + TAB + featureSource + TAB + featureType + TAB + featureStart + TAB + featureEnd + TAB + featureScore + TAB + featureStrand + TAB + featurePhase + TAB + featureAttributes + "\n"
-		gffBuffer.WriteString(featureString)
-	}
-
-	gffBuffer.WriteString("###\n")
-	gffBuffer.WriteString("##FASTA\n")
-	gffBuffer.WriteString(">" + sequence.Meta.Name + "\n")
-
-	for letterIndex, letter := range sequence.Sequence {
-		letterIndex++
-		if letterIndex%70 == 0 && letterIndex != 0 && letterIndex != sequence.Meta.RegionEnd {
-			gffBuffer.WriteRune(letter)
-			gffBuffer.WriteString("\n")
-		} else {
-			gffBuffer.WriteRune(letter)
-		}
-	}
-	gffBuffer.WriteString("\n")
-	return gffBuffer.Bytes(), nil
-}
-
-// Read takes in a filepath for a .gffv3 file and parses it into an Annotated poly.Sequence struct.
-func Read(path string) (Gff, error) {
-	file, err := openFn(path)
-	if err != nil {
-		return Gff{}, err
-	}
-
-	sequence, err := Parse(file)
-	return sequence, err
-}
-
-// Write takes an poly.Sequence struct and a path string and writes out a gff to that path.
-func Write(sequence Gff, path string) error {
-	gff, _ := Build(sequence)
-	return os.WriteFile(path, gff, 0644)
-}


Test patch:
diff --git a/lib/bio/gff/example_test.go b/lib/bio/gff/example_test.go
deleted file mode 100644
index 7be3d8e..0000000
--- a/lib/bio/gff/example_test.go
+++ /dev/null
@@ -1,170 +0,0 @@
-package gff_test
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"path/filepath"
-	"testing"
-
-	"github.com/koeng101/dnadesign/lib/bio/gff"
-	"github.com/koeng101/dnadesign/lib/transform"
-)
-
-// This example shows how to open a gff file and search for a gene given its
-// locus tag. We then display the EC number of that particular gene.
-func Example_basic() {
-	sequence, _ := gff.Read("../../data/ecoli-mg1655-short.gff")
-	for _, feature := range sequence.Features {
-		if feature.Attributes["locus_tag"] == "b0003" {
-			fmt.Println(feature.Attributes["EC_number"])
-		}
-	}
-	// Output: 2.7.1.39
-}
-
-func ExampleRead() {
-	sequence, _ := gff.Read("../../data/ecoli-mg1655-short.gff")
-	fmt.Println(sequence.Meta.Name)
-	// Output: U00096.3
-}
-
-func ExampleParse() {
-	file, _ := os.Open("../../data/ecoli-mg1655-short.gff")
-	sequence, _ := gff.Parse(file)
-
-	fmt.Println(sequence.Meta.Name)
-	// Output: U00096.3
-}
-
-func ExampleBuild() {
-	sequence, _ := gff.Read("../../data/ecoli-mg1655-short.gff")
-	gffBytes, _ := gff.Build(sequence)
-	gffReader := bytes.NewReader(gffBytes)
-	reparsedSequence, _ := gff.Parse(gffReader)
-
-	fmt.Println(reparsedSequence.Meta.Name)
-	// Output: U00096.3
-}
-
-func ExampleWrite() {
-	tmpDataDir, err := os.MkdirTemp("", "data-*")
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	defer os.RemoveAll(tmpDataDir)
-
-	sequence, _ := gff.Read("../../data/ecoli-mg1655-short.gff")
-
-	tmpGffFilePath := filepath.Join(tmpDataDir, "ecoli-mg1655-short.gff")
-	_ = gff.Write(sequence, tmpGffFilePath)
-
-	testSequence, _ := gff.Read(tmpGffFilePath)
-
-	fmt.Println(testSequence.Meta.Name)
-	// Output: U00096.3
-}
-
-func ExampleGff_AddFeature() {
-	// Sequence for greenflourescent protein (GFP) that we're using as test data for this example.
-	gfpSequence := "ATGGCTAGCAAAGGAGAAGAACTTTTCACTGGAGTTGTCCCAATTCTTGTTGAATTAGATGGTGATGTTAATGGGCACAAATTTTCTGTCAGTGGAGAGGGTGAAGGTGATGCTACATACGGAAAGCTTACCCTTAAATTTATTTGCACTACTGGAAAACTACCTGTTCCATGGCCAACACTTGTCACTACTTTCTCTTATGGTGTTCAATGCTTTTCCCGTTATCCGGATCATATGAAACGGCATGACTTTTTCAAGAGTGCCATGCCCGAAGGTTATGTACAGGAACGCACTATATCTTTCAAAGATGACGGGAACTACAAGACGCGTGCTGAAGTCAAGTTTGAAGGTGATACCCTTGTTAATCGTATCGAGTTAAAAGGTATTGATTTTAAAGAAGATGGAAACATTCTCGGACACAAACTCGAGTACAACTATAACTCACACAATGTATACATCACGGCAGACAAACAAAAGAATGGAATCAAAGCTAACTTCAAAATTCGCCACAACATTGAAGATGGATCCGTTCAACTAGCAGACCATTATCAACAAAATACTCCAATTGGCGATGGCCCTGTCCTTTTACCAGACAACCATTACCTGTCGACACAATCTGCCCTTTCGAAAGATCCCAACGAAAAGCGTGACCACATGGTCCTTCTTGAGTTTGTAACTGCTGCTGGGATTACACATGGCATGGATGAGCTCTACAAATAA"
-
-	// initialize sequence and feature structs.
-	var sequence gff.Gff
-	var feature gff.Feature
-
-	// set the initialized sequence struct's sequence.
-	sequence.Sequence = gfpSequence
-
-	// Set the initialized feature name and sequence location.
-	feature.Location = gff.Location{}
-	feature.Location.Start = 0
-	feature.Location.End = len(sequence.Sequence)
-
-	// Add the GFP feature to the sequence struct.
-	_ = sequence.AddFeature(&feature)
-
-	// get the GFP feature sequence string from the sequence struct.
-	featureSequence, _ := feature.GetSequence()
-
-	// check to see if the feature was inserted properly into the sequence.
-	fmt.Println(gfpSequence == featureSequence)
-
-	// Output: true
-}
-
-func ExampleFeature_GetSequence() {
-	// Sequence for greenflourescent protein (GFP) that we're using as test data for this example.
-	gfpSequence := "ATGGCTAGCAAAGGAGAAGAACTTTTCACTGGAGTTGTCCCAATTCTTGTTGAATTAGATGGTGATGTTAATGGGCACAAATTTTCTGTCAGTGGAGAGGGTGAAGGTGATGCTACATACGGAAAGCTTACCCTTAAATTTATTTGCACTACTGGAAAACTACCTGTTCCATGGCCAACACTTGTCACTACTTTCTCTTATGGTGTTCAATGCTTTTCCCGTTATCCGGATCATATGAAACGGCATGACTTTTTCAAGAGTGCCATGCCCGAAGGTTATGTACAGGAACGCACTATATCTTTCAAAGATGACGGGAACTACAAGACGCGTGCTGAAGTCAAGTTTGAAGGTGATACCCTTGTTAATCGTATCGAGTTAAAAGGTATTGATTTTAAAGAAGATGGAAACATTCTCGGACACAAACTCGAGTACAACTATAACTCACACAATGTATACATCACGGCAGACAAACAAAAGAATGGAATCAAAGCTAACTTCAAAATTCGCCACAACATTGAAGATGGATCCGTTCAACTAGCAGACCATTATCAACAAAATACTCCAATTGGCGATGGCCCTGTCCTTTTACCAGACAACCATTACCTGTCGACACAATCTGCCCTTTCGAAAGATCCCAACGAAAAGCGTGACCACATGGTCCTTCTTGAGTTTGTAACTGCTGCTGGGATTACACATGGCATGGATGAGCTCTACAAATAA"
-
-	// initialize sequence and feature structs.
-	var sequence gff.Gff
-	var feature gff.Feature
-
-	// set the initialized sequence struct's sequence.
-	sequence.Sequence = gfpSequence
-
-	// Set the initialized feature name and sequence location.
-	feature.Location.Start = 0
-	feature.Location.End = len(sequence.Sequence)
-
-	// Add the GFP feature to the sequence struct.
-	_ = sequence.AddFeature(&feature)
-
-	// get the GFP feature sequence string from the sequence struct.
-	featureSequence, _ := feature.GetSequence()
-
-	// check to see if the feature was inserted properly into the sequence.
-	fmt.Println(gfpSequence == featureSequence)
-
-	// Output: true
-}
-
-func TestFeature_GetSequence(t *testing.T) {
-	// This test is a little too complex and contrived for an example function.
-	// Essentially, it's testing GetSequence()'s ability to parse and retrieve sequences from complex location structures.
-	// This was originally covered in the old package system  it was not covered in the new package system so I decided to include it here.
-
-	// Sequence for greenflourescent protein (GFP) that we're using as test data for this example.
-	gfpSequence := "ATGGCTAGCAAAGGAGAAGAACTTTTCACTGGAGTTGTCCCAATTCTTGTTGAATTAGATGGTGATGTTAATGGGCACAAATTTTCTGTCAGTGGAGAGGGTGAAGGTGATGCTACATACGGAAAGCTTACCCTTAAATTTATTTGCACTACTGGAAAACTACCTGTTCCATGGCCAACACTTGTCACTACTTTCTCTTATGGTGTTCAATGCTTTTCCCGTTATCCGGATCATATGAAACGGCATGACTTTTTCAAGAGTGCCATGCCCGAAGGTTATGTACAGGAACGCACTATATCTTTCAAAGATGACGGGAACTACAAGACGCGTGCTGAAGTCAAGTTTGAAGGTGATACCCTTGTTAATCGTATCGAGTTAAAAGGTATTGATTTTAAAGAAGATGGAAACATTCTCGGACACAAACTCGAGTACAACTATAACTCACACAATGTATACATCACGGCAGACAAACAAAAGAATGGAATCAAAGCTAACTTCAAAATTCGCCACAACATTGAAGATGGATCCGTTCAACTAGCAGACCATTATCAACAAAATACTCCAATTGGCGATGGCCCTGTCCTTTTACCAGACAACCATTACCTGTCGACACAATCTGCCCTTTCGAAAGATCCCAACGAAAAGCGTGACCACATGGTCCTTCTTGAGTTTGTAACTGCTGCTGGGATTACACATGGCATGGATGAGCTCTACAAATAA"
-
-	sequenceLength := len(gfpSequence)
-
-	// Splitting the sequence into two parts to make a multi-location feature.
-	sequenceFirstHalf := gfpSequence[:sequenceLength/2]
-	sequenceSecondHalf := transform.ReverseComplement(gfpSequence[sequenceLength/2:]) // This feature is reverse complemented.
-
-	// rejoining the two halves into a single string where the second half of the sequence is reverse complemented.
-	gfpSequenceModified := sequenceFirstHalf + sequenceSecondHalf
-
-	// initialize sequence and feature structs.
-	var sequence gff.Gff
-	var feature gff.Feature
-
-	// set the initialized sequence struct's sequence.
-	sequence.Sequence = gfpSequenceModified
-	// initialize sublocations to be usedin the feature.
-
-	var subLocation gff.Location
-	var subLocationReverseComplemented gff.Location
-
-	subLocation.Start = 0
-	subLocation.End = sequenceLength / 2
-
-	subLocationReverseComplemented.Start = sequenceLength / 2
-	subLocationReverseComplemented.End = sequenceLength
-	subLocationReverseComplemented.Complement = true // According to genbank complement means reverse complement. What a country.
-
-	feature.Location.SubLocations = []gff.Location{subLocation, subLocationReverseComplemented}
-
-	// Add the GFP feature to the sequence struct.
-	_ = sequence.AddFeature(&feature)
-
-	// get the GFP feature sequence string from the sequence struct.
-	featureSequence, _ := feature.GetSequence()
-
-	// check to see if the feature was inserted properly into the sequence.
-	if gfpSequence != featureSequence {
-		t.Error("Feature sequence was not properly retrieved.")
-	}
-}
diff --git a/lib/bio/gff/gff_test.go b/lib/bio/gff/gff_test.go
deleted file mode 100644
index 7a6e029..0000000
--- a/lib/bio/gff/gff_test.go
+++ /dev/null
@@ -1,146 +0,0 @@
-package gff
-
-import (
-	"bytes"
-	"errors"
-	"io"
-	"os"
-	"path/filepath"
-	"strings"
-	"testing"
-
-	"github.com/google/go-cmp/cmp"
-	"github.com/google/go-cmp/cmp/cmpopts"
-	"github.com/pmezard/go-difflib/difflib"
-)
-
-/******************************************************************************
-
-Gff related tests and benchmarks begin here.
-
-******************************************************************************/
-
-// TODO should delete output files.
-
-func TestGffIO(t *testing.T) {
-	tmpDataDir, err := os.MkdirTemp("", "data-*")
-	if err != nil {
-		t.Error(err)
-	}
-	defer os.RemoveAll(tmpDataDir)
-
-	testInputPath := "../../data/ecoli-mg1655-short.gff"
-	tmpGffFilePath := filepath.Join(tmpDataDir, "ecoli-mg1655-short.gff")
-
-	testSequence, _ := Read(testInputPath)
-	_ = Write(testSequence, tmpGffFilePath)
-
-	readTestSequence, _ := Read(tmpGffFilePath)
-
-	if diff := cmp.Diff(testSequence, readTestSequence, cmpopts.IgnoreFields(Feature{}, "ParentSequence")); diff != "" {
-		t.Errorf("Parsing the output of Build() does not produce the same output as parsing the original file read with ReadGff(). Got this diff:\n%s", diff)
-	}
-
-	original, _ := os.ReadFile(testInputPath)
-	builtOutput, _ := os.ReadFile(tmpGffFilePath)
-	gffDiff := difflib.UnifiedDiff{
-		A:        difflib.SplitLines(string(original)),
-		B:        difflib.SplitLines(string(builtOutput)),
-		FromFile: testInputPath,
-		ToFile:   tmpGffFilePath,
-		Context:  3,
-	}
-
-	gffDiffText, _ := difflib.GetUnifiedDiffString(gffDiff)
-
-	if gffDiffText != "" {
-		t.Errorf("Build() does not output the same file as was input through ReadGff(). Got this diff:\n%s", gffDiffText)
-	}
-}
-
-// testing that readAllFn() returns an error.
-func TestParseReader_error(t *testing.T) {
-	parseErr := errors.New("parse error")
-	oldReadAllFn := readAllFn
-	readAllFn = func(r io.Reader) ([]byte, error) {
-		return nil, parseErr
-	}
-	defer func() {
-		readAllFn = oldReadAllFn
-	}()
-	_, err := Parse(strings.NewReader(""))
-	if err != parseErr {
-		t.Errorf("Parse() did not return the expected error. Got %v, expected %v", err, parseErr)
-	}
-}
-
-// testing that all Atoi() calls return an error.
-func TestParseAtoi_error(t *testing.T) {
-	file, _ := openFn("../../data/ecoli-mg1655-short.gff")
-	fileBytes, _ := readAllFn(file)
-	fileString := string(fileBytes)
-	recievedAtoiInputs := []string{}
-
-	parseErr := errors.New("parse error")
-	oldAtoiFn := atoiFn
-	// helper function to see if the input string for atoiFn is in the recievedAtoiInputs slice.
-	contains := func(stringSlice []string, expression string) bool {
-		for _, input := range stringSlice {
-			if input == expression {
-				return true
-			}
-		}
-		return false
-	}
-	atoiFn = func(gffString string) (int, error) {
-		if !contains(recievedAtoiInputs, gffString) {
-			recievedAtoiInputs = append(recievedAtoiInputs, gffString)
-			// length = len(recievedAtoiInputs)
-			return 0, parseErr
-		}
-		return oldAtoiFn(gffString)
-	}
-
-	defer func() {
-		atoiFn = oldAtoiFn
-	}()
-	for index := 0; index <= 10; index++ {
-		var gffBuffer bytes.Buffer
-		gffBuffer.WriteString(fileString)
-		_, _ = Parse(&gffBuffer)
-	}
-}
-
-// testing that Read can return an appropriate error.
-func TestRead_error(t *testing.T) {
-	readErr := errors.New("open : no such file or directory")
-	oldOpenFn := openFn
-	openFn = func(filepath string) (*os.File, error) {
-		return nil, readErr
-	}
-	defer func() {
-		openFn = oldOpenFn
-	}()
-	_, err := Read("../../data/ecoli-mg1655-short.gff")
-	if err != readErr {
-		t.Errorf("Read() did not return the expected error. Got %v, expected %v", err, readErr)
-	}
-}
-
-func BenchmarkReadGff(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		_, _ = Read("../../data/ecoli-mg1655-short.gff")
-	}
-}
-
-func BenchmarkReadGff1(b *testing.B)     { BenchmarkReadGff(b) }
-func BenchmarkReadGff10(b *testing.B)    { BenchmarkReadGff(b) }
-func BenchmarkReadGff100(b *testing.B)   { BenchmarkReadGff(b) }
-func BenchmarkReadGff1000(b *testing.B)  { BenchmarkReadGff(b) }
-func BenchmarkReadGff10000(b *testing.B) { BenchmarkReadGff(b) }
-
-/******************************************************************************
-
-Gff related tests and benchmarks end here.
-
-******************************************************************************/