Skip to content

Commit

Permalink
Refactoring loading procedure
Browse files Browse the repository at this point in the history
  • Loading branch information
Cristiano Alves da Silva Junior committed Sep 28, 2018
1 parent 5efac70 commit 0d86951
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 91 deletions.
5 changes: 3 additions & 2 deletions edfOps.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ func (edf Edf) GetDataRecords() int {

// Appends data from one EDF to another. Returns a new EDF object and an error,
// which is `nil` if everything runs ok. This function requires the
// EDF files to have the same sampling rate and the same number of channels.
// EDF files to have the same sampling rate, the same number of channels,
// and the same duration for each data record.
//
// This function is in experimental state and must be used carefully!
func Append(x, y Edf) (*Edf, error) {
Expand All @@ -116,7 +117,7 @@ func Append(x, y Edf) (*Edf, error) {
z := NewEdf(x.Header, x.Records)

// Updating header
z.Header["datarecords"] = EnforceSize(strconv.Itoa(x.GetDataRecords() + y.GetDataRecords()), 8)
z.Header["datarecords"] = EnforceSize(strconv.Itoa(x.GetDataRecords() + y.GetDataRecords()), GetSpecsLength()["datarecords"])

// Appending data records
for i := 0; i < len(x.Records); i++ {
Expand Down
187 changes: 98 additions & 89 deletions edfReader.go
Original file line number Diff line number Diff line change
@@ -1,127 +1,136 @@
package edf

import "os"
import "bytes"
import "encoding/binary"
import (
"os"
"bytes"
"encoding/binary"
)

/* --- MAIN FUNCTIONS --- */

// Reads and EDF file, parsing it into the header and the records.
// The header will be a map relating the properties to a string with the raw data
// The records will be a matrix storing the raw bytes in the file
func ReadFile(input string) Edf {
inlet, err := os.Open(input)
inlet, err := os.Open(input)

if err != nil {
panic(err)
}
if err != nil {
panic(err)
}

defer inlet.Close()
header := ReadHeader(inlet)
records := ReadRecords(inlet, header)
defer inlet.Close()
header := ReadHeader(inlet)
records := ReadRecords(inlet, header)

return NewEdf(header, records)
return NewEdf(header, records)
}

// Reads the header of an EDF file. Requires the opened EDF file, the list of
// specifications and the length in bytes for each of them, as described by
// the EDF standard. The specs can be accessed though the GetSpecsList
// function, and their lenghts through the GetSpecsLength one.
func ReadHeader(inlet *os.File) map[string]string {
specsList := GetSpecsList()
specsLength := GetSpecsLength()
header := make(map[string]string)
index := 0

// Reading header's header
for index < len(specsList) {
spec := specsList[index]

if spec == "label" {
break
} else {
data := make([]byte, specsLength[spec])
n, _ := inlet.Read(data)
header[spec] = string(data[:n])
}

index++
}

// Reading header's records
numberSignals := getNumberSignals(header)
for index = index; index < len(specsList); index++ {
spec := specsList[index]
data := make([]byte, specsLength[spec] * numberSignals)
n, _ := inlet.Read(data)
header[spec] = string(data[:n])
}

return header
specsList := GetSpecsList()
specsLength := GetSpecsLength()
header := make(map[string]string)
index := 0

// Reading header's header
for index < len(specsList) {
spec := specsList[index]

if spec == "label" {
break
} else {
data := make([]byte, specsLength[spec])
n, _ := inlet.Read(data)
header[spec] = string(data[:n])
}

index++
}

// Reading header's records
numberSignals := getNumberSignals(header)
for index = index; index < len(specsList); index++ {
spec := specsList[index]
data := make([]byte, specsLength[spec] * numberSignals)
n, _ := inlet.Read(data)
header[spec] = string(data[:n])
}

return header
}

// Reads the data records from the EDF file. Its parameters are the pointer to
// file; and header information, as returned by the ReadHeader function.
func ReadRecords(inlet *os.File, header map[string]string) [][]int16 {
numberSignals := getNumberSignals(header)
numberSamples := getNumberSamples(header)
records := make([][]int16, numberSignals)
sampling := make([]int, numberSignals)
duration := str2int(header["duration"])
dataRecords := str2int(header["datarecords"])

// setup records
for i := 0; i < numberSignals; i++ {
sampling[i] = duration * numberSamples[i]
records[i] = make([]int16, sampling[i])
}

// translate data
for d := 0; d < dataRecords; d++ {
for i := 0; i < numberSignals; i++ {
data := make([]byte, 2*sampling[i])
inlet.Read(data)
records[i] = appendInt16Arrays(records[i], translate(data))
}
}

return records
numberSignals := getNumberSignals(header)
numberSamples := getNumberSamples(header)
records := make([][]int16, numberSignals)
sampling := make([]int, numberSignals)
duration := str2int(header["duration"])
dataRecords := str2int(header["datarecords"])

// setup records
for i := 0; i < numberSignals; i++ {
sampling[i] = duration * numberSamples[i]
records[i] = make([]int16, sampling[i])
}

// Reading records
dataRecordsSize := 2 * dataRecords * Sigma(sampling)
data := make([]byte, dataRecordsSize)
inlet.Read(data)

// translate data
i := 0
for d := 0; d < dataRecords; d++ {
for s := 0; s < numberSignals; s++ {
step := 2*sampling[s]
piece := data[i:i+step]
records[s] = appendInt16Arrays(records[s], translate(piece))
i += step
}
}

return records
}


/* --- AUXILIAR FUNCTIONS --- */
func translate(inlet []byte) []int16 {
var data int16
limit := len(inlet)/2
outlet := make([]int16, limit)
buffer := bytes.NewReader(inlet)

for i := 0; i < limit; i++ {
// oops := binary.Read(buffer, binary.BigEndian, &data)
oops := binary.Read(buffer, binary.LittleEndian, &data)
if oops == nil {
outlet[i] = data
} else {
panic(oops)
}
}

return outlet
var data int16
limit := len(inlet)/2
outlet := make([]int16, limit)
buffer := bytes.NewReader(inlet)

for i := 0; i < limit; i++ {
// oops := binary.Read(buffer, binary.BigEndian, &data)
oops := binary.Read(buffer, binary.LittleEndian, &data)
if oops == nil {
outlet[i] = data
} else {
panic(oops)
}
}

return outlet
}

func getNumberSignals(header map[string]string) int {
raw := header["numbersignals"]
return str2int(raw)
raw := header["numbersignals"]
return str2int(raw)
}

func getNumberSamples(header map[string]string) []int {
numberSignals := getNumberSignals(header)
numberSamples := make([]int, numberSignals)
samples := separateString(header["samplesrecord"], numberSignals)
numberSignals := getNumberSignals(header)
numberSamples := make([]int, numberSignals)
samples := separateString(header["samplesrecord"], numberSignals)

for i := 0; i < numberSignals; i++ {
numberSamples[i] = str2int(samples[i])
}
for i := 0; i < numberSignals; i++ {
numberSamples[i] = str2int(samples[i])
}

return numberSamples
return numberSamples
}
9 changes: 9 additions & 0 deletions useful.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,12 @@ func EnforceSize(field string, limit int) string {

return field
}

// Sums all values of an int array
func Sigma(a []int) int {
r := 0
for i := 0; i < len(a); i++ {
r += a[i]
}
return r
}

0 comments on commit 0d86951

Please sign in to comment.