-
Notifications
You must be signed in to change notification settings - Fork 0
/
hbv_io.go
179 lines (147 loc) · 4.12 KB
/
hbv_io.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
This file contains I/O functions to read and write model and data files,
as well as defitions of structs for data.
To be implemented/wip:
Struct for holding model results.
Read parameters csv (many parameter sets, output array of par struct)
Read parameters nested json (many parameter sets, output array of par struct)
Write timeseries output (wip, need to include dates and refine a bit, exclude warmup time)
Write summary output (input struct with summarized goodness of fit and file path (exclude warmup), output none)
Write batch output (Simulation based on many parameter sets)
*/
package gohbv
import (
"encoding/csv"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strconv"
)
// Parameters struct
type Parameters struct {
TT float64
CFMAX float64
SFCF float64
CFR float64
CWH float64
FC float64
LP float64
BETA float64
PERC float64
UZL float64
K0 float64
K1 float64
K2 float64
MAXBAS float64
PCALT float64
TCALT float64
}
// Input forcing and observations
type InputData struct {
Date string
Precipitation float64
Temperature float64
Discharge float64
PotentialET float64
}
// Not yet in use
// type OutputData struct {
// Date string
// SimulatedQ float64
// }
// Parse input data csv rows to InputData struct
func ParseInputData(r [][]string) ([]InputData, error) {
var indata []InputData = make([]InputData, len(r))
var err error
for i, row := range r {
indata[i].Date = row[0]
indata[i].Precipitation, err = strconv.ParseFloat(row[1], 64)
if err != nil {
fmt.Printf("Error converting Precipitation string: %v", err)
}
indata[i].Temperature, err = strconv.ParseFloat(row[2], 64)
if err != nil {
fmt.Printf("Error converting Temperature string: %v", err)
}
indata[i].Discharge, err = strconv.ParseFloat(row[3], 64)
if err != nil {
fmt.Printf("Error converting Discharge string: %v", err)
}
indata[i].PotentialET, err = strconv.ParseFloat(row[4], 64)
if err != nil {
fmt.Printf("Error converting PotentialET string: %v", err)
}
}
return indata, nil
}
// Read csv input forcing data to InputData struct
// CSV data must be in order Date, Precipitation, Temperature, Discharge, Potential ET
func ReadInputData(inputDataFile string) []InputData {
csvFile, err := os.Open(inputDataFile)
if err != nil {
fmt.Println(err)
}
defer csvFile.Close()
csvReader := csv.NewReader(csvFile)
_, _ = csvReader.Read() // Read() reads first line which is just the header, not part of data. Needed to skip line for data
csvLines, err := csvReader.ReadAll()
if err != nil {
fmt.Println(err)
}
inData, err := ParseInputData(csvLines)
if err != nil {
fmt.Println(err)
}
return inData
}
// Parse parameter .json file
// Unmarshal to Parameters struct
func ParseParameters(jsonData []byte) (Parameters, error) {
var pars Parameters
err := json.Unmarshal(jsonData, &pars)
if err != nil {
fmt.Printf("Error: %v", err)
}
return pars, nil
}
// Read parameter json file and parse it to Parameters struct
func ReadParameters(parameterFile string) Parameters {
jsonFileObj, err := os.Open(parameterFile)
if err != nil {
fmt.Println(err)
}
// defer closing so we can parse it later
defer jsonFileObj.Close()
// read parameter json as byte
parsByte, _ := ioutil.ReadAll(jsonFileObj)
pars, _ := ParseParameters(parsByte)
return pars
}
// Write model result (array of ModelState structs) to outputFile
func WriteCSVResults(mState []ModelState, outputFile string) {
fmt.Println(outputFile)
file, err := os.Create(outputFile)
if err != nil {
fmt.Println(err)
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
// Write header
err = writer.Write([]string{"S_snow", "Recharge_gwuz", "S_soil", "S_gw_suz", "Q"})
if err != nil {
fmt.Println(err)
}
for _, value := range mState {
err := writer.Write([]string{
strconv.FormatFloat(value.S_snow, 'f', 4, 64),
strconv.FormatFloat(value.Recharge_gwuz, 'f', 4, 64),
strconv.FormatFloat(value.S_soil, 'f', 4, 64),
strconv.FormatFloat(value.S_gw_suz, 'f', 4, 64),
strconv.FormatFloat(value.Q_sim, 'f', 4, 64)})
if err != nil {
fmt.Println(err)
}
}
}