ak9im/p3/data.go

249 lines
4.0 KiB
Go

package main
import (
"encoding/csv"
"errors"
"io"
"io/fs"
"io/ioutil"
"log"
"os"
"regexp"
"strconv"
)
func readData(f *os.File) ([][]float64, error) {
records := make([][]string, 0, 251)
r := csv.NewReader(f)
for {
record, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
records = append(records, record)
}
data, err := parseRecords(records)
if err != nil {
return nil, err
}
return data, nil
}
func parseRecords(r [][]string) ([][]float64, error) {
if len(r) == 0 {
return nil, errors.New("ErrNoRecords")
}
// remove the header.
r = r[1:]
u := 0
y := 1
data := [][]float64{make([]float64, 0, len(r)), make([]float64, 0, len(r))}
for _, uy := range r {
fu, err := strconv.ParseFloat(uy[u], 64)
if err != nil {
return nil, err
}
fy, err := strconv.ParseFloat(uy[y], 64)
if err != nil {
return nil, err
}
data[u] = append(data[u], fu)
data[y] = append(data[y], fy)
}
return data, nil
}
func readFile(s *string) ([][]float64, error) {
f, err := os.Open(*s)
if err != nil {
return nil, err
}
defer f.Close()
data, err := readData(f)
if err != nil {
return nil, err
}
return data, nil
}
// nolint: gocognit
func saveStuff(
meanU, meanY,
varianceU, varianceY,
cov float64,
autocorrelationU, autocorrelationY,
mutCorrelationUY, mutCorrelationYU,
errVals []float64,
theta, thetaT [][]float64,
) error {
fFnames := map[string]float64{
"mean_u": meanU,
"mean_y": meanY,
"variance_u": varianceU,
"variance_y": varianceY,
"covariance_uy": cov,
}
sFnames := map[string][]float64{
"autocorrelation_u": autocorrelationU,
"autocorrelation_y": autocorrelationY,
"mutual_correlation_uy": mutCorrelationUY,
"mutual_correlation_yu": mutCorrelationYU,
"estimate_error": errVals,
}
smFnames := map[string][][]float64{
"theta": theta,
"thetaT": theta,
}
prefix := "data/"
suffix := ".txt"
for k, v := range fFnames {
f, err := os.Create(prefix + k + suffix)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(strconv.FormatFloat(v, 'f', 64, 64))
if err != nil {
return err
}
}
suffix = ".csv"
for k, v := range sFnames {
f, err := os.Create(prefix + k + suffix)
if err != nil {
return err
}
defer f.Close()
w := csv.NewWriter(f)
s := recordsFromFloat64Slice(v)
err = w.WriteAll(s)
if err != nil {
return err
}
}
for k, v := range smFnames {
if k == "thetaT" {
for i := range thetaT {
th := theta[i]
f, err := os.Create(prefix + k + "_p" + strconv.Itoa(i) + suffix)
if err != nil {
return err
}
defer f.Close()
w := csv.NewWriter(f)
s := recordsFromFloat64Slice(th)
err = w.WriteAll(s)
if err != nil {
return err
}
}
}
f, err := os.Create(prefix + k + suffix)
if err != nil {
return err
}
w := csv.NewWriter(f)
s := recordsFromSliceFloat64Slice(v)
err = w.WriteAll(s)
if err != nil {
return err
}
// since we need the file soon, close it now.
err = f.Close()
if err != nil {
return err
}
{
reread, err := ioutil.ReadFile(prefix + k + suffix)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
log.Println("apparently this file has not been written yet")
}
return err
}
// remove double quotes.
cleared := regexp.MustCompile(`("?;"|";"?)|"`).ReplaceAll(reread, []byte("${1}"))
if err = ioutil.WriteFile(prefix+k+suffix, cleared, 0o600); err != nil {
return err
}
}
}
return nil
}
func recordsFromFloat64Slice(f []float64) [][]string {
s := make([][]string, 0, len(f))
for i := range f {
tmp := strconv.FormatFloat(f[i], 'f', 64, 64)
s = append(s, []string{tmp})
}
return s
}
func recordsFromSliceFloat64Slice(f [][]float64) [][]string {
s := make([][]string, 0, len(f))
for i := range f {
row := ""
for j := range f[i] {
tmp := strconv.FormatFloat(f[i][j], 'f', 64, 64)
if j == 0 {
row += tmp
} else {
row += ", " + tmp
}
}
s = append(s, []string{row})
}
return s
}