Skip to content

Commit c8565d9

Browse files
add csv hazardprovider
1 parent c1a5dcd commit c8565d9

4 files changed

Lines changed: 182 additions & 5 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package hazardproviders
2+
3+
import (
4+
"encoding/csv"
5+
"fmt"
6+
"os"
7+
"strconv"
8+
"strings"
9+
"time"
10+
11+
"github.com/USACE/go-consequences/geography"
12+
"github.com/USACE/go-consequences/hazards"
13+
)
14+
15+
type csvArrivalDepthDurationMultiHazardProvider struct {
16+
f *os.File
17+
arrivals []time.Time
18+
depths []float64
19+
durations []float64
20+
process HazardFunction
21+
bbox geography.BBox
22+
}
23+
24+
func InitCSV(fp string, b geography.BBox) (csvArrivalDepthDurationMultiHazardProvider, error) {
25+
fmt.Println("Connecting to: " + fp)
26+
file, err := os.Open(fp)
27+
if err != nil {
28+
panic(err)
29+
}
30+
31+
reader := csv.NewReader(file)
32+
33+
rows, err := reader.ReadAll()
34+
if err != nil {
35+
panic(err)
36+
}
37+
arrivals := make([]time.Time, len(rows)-1)
38+
depths := make([]float64, len(rows)-1)
39+
durations := make([]float64, len(rows)-1)
40+
41+
for i, row := range rows[1:] {
42+
year, err := strconv.Atoi(row[2])
43+
if err != nil {
44+
panic(err)
45+
}
46+
month, err := strconv.Atoi(strings.TrimSpace(row[3]))
47+
if err != nil {
48+
panic(err)
49+
}
50+
day, err := strconv.Atoi(strings.TrimSpace(row[4]))
51+
if err != nil {
52+
panic(err)
53+
}
54+
at := time.Date(year, time.Month(month), int(day), 0, 0, 0, 0, time.UTC)
55+
depth, err := strconv.ParseFloat(row[5], 64)
56+
if err != nil {
57+
panic(err)
58+
}
59+
dur, err := strconv.ParseFloat(row[6], 64)
60+
if err != nil {
61+
panic(err)
62+
}
63+
64+
arrivals[i] = at
65+
depths[i] = depth
66+
durations[i] = dur
67+
}
68+
69+
return csvArrivalDepthDurationMultiHazardProvider{
70+
f: file,
71+
arrivals: arrivals,
72+
depths: depths,
73+
durations: durations,
74+
process: ArrivalDepthAndDurationHazardFunction(),
75+
bbox: b,
76+
}, nil
77+
78+
}
79+
80+
func (c csvArrivalDepthDurationMultiHazardProvider) Close() {
81+
c.f.Close()
82+
}
83+
84+
func (c csvArrivalDepthDurationMultiHazardProvider) Hazard(l geography.Location) (hazards.HazardEvent, error) {
85+
var hm hazards.ArrivalDepthandDurationEventMulti
86+
if c.bbox.Contains(l) {
87+
for i, d := range c.depths {
88+
hd := hazards.HazardData{
89+
Depth: d,
90+
Velocity: 0,
91+
ArrivalTime: c.arrivals[i],
92+
Erosion: 0,
93+
Duration: c.durations[i],
94+
WaveHeight: 0,
95+
Salinity: false,
96+
Qualitative: "",
97+
}
98+
var h hazards.HazardEvent
99+
h, err := c.process(hd, h)
100+
if err != nil {
101+
panic(err)
102+
}
103+
hm.Append(h.(hazards.ArrivalDepthandDurationEvent))
104+
}
105+
}
106+
return &hm, nil
107+
}
108+
109+
func (c csvArrivalDepthDurationMultiHazardProvider) HazardBoundary() (geography.BBox, error) {
110+
return c.bbox, nil
111+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package hazardproviders
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/USACE/go-consequences/geography"
8+
"github.com/USACE/go-consequences/hazards"
9+
)
10+
11+
func TestInitCSV(t *testing.T) {
12+
file := "/workspaces/go-consequences/data/lifecycle/test_arrival-depth-duration_hazards.csv"
13+
14+
expectedDepths := []float64{1.0, 1.0, 1.0, 2.0, 2.0}
15+
expectedDurations := []float64{0.0, 5.0, 0.0, 0.0, 0.0}
16+
et1 := time.Date(1984, time.Month(1), 1, 0, 0, 0, 0, time.UTC)
17+
et2 := time.Date(1984, time.Month(1), 11, 0, 0, 0, 0, time.UTC)
18+
et3 := time.Date(1984, time.Month(1), 21, 0, 0, 0, 0, time.UTC)
19+
et4 := time.Date(1985, time.Month(1), 1, 0, 0, 0, 0, time.UTC)
20+
et5 := time.Date(1985, time.Month(1), 11, 0, 0, 0, 0, time.UTC)
21+
expectedArrivals := []time.Time{et1, et2, et3, et4, et5}
22+
23+
b := geography.BBox{
24+
// xMin, yMin, xMax, yMax
25+
Bbox: []float64{-71.1, 43, -71, 43.1},
26+
}
27+
ADDMHP, err := InitCSV(file, b)
28+
if err != nil {
29+
panic(err)
30+
}
31+
defer ADDMHP.Close()
32+
33+
loc := geography.Location{
34+
X: -71.05,
35+
Y: 43.05,
36+
SRID: "",
37+
}
38+
39+
haz, err := ADDMHP.Hazard(loc)
40+
h := haz.(*hazards.ArrivalDepthandDurationEventMulti)
41+
if err != nil {
42+
panic(err)
43+
}
44+
45+
for {
46+
edepth := expectedDepths[h.Index()]
47+
edur := expectedDurations[h.Index()]
48+
earr := expectedArrivals[h.Index()]
49+
50+
if h.Depth() != edepth {
51+
t.Errorf("Event at index %d had Depth = %v. Expected: %3.2f", h.Index(), h.Depth(), edepth)
52+
}
53+
if h.Duration() != edur {
54+
t.Errorf("Event at index %d had Duration = %v. Expected: %3.2f", h.Index(), h.Duration(), edur)
55+
}
56+
if h.Depth() != edepth {
57+
t.Errorf("Event at index %d had ArrivalTime = %v. Expected: %v", h.Index(), h.ArrivalTime(), earr)
58+
}
59+
60+
if h.HasNext() {
61+
h.Increment()
62+
} else {
63+
break
64+
}
65+
}
66+
}

hazardproviders/json_multi_hazard.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ type jsonArrivalDepthDurationMultiHazardProvider struct {
1717
process HazardFunction
1818
}
1919

20-
type ADDProperties struct { // will try to not use this
20+
type ADDProperties struct {
2121
Year float64 `json:"year"`
2222
Month float64 `json:"month"`
2323
Day float64 `json:"day"`
@@ -93,6 +93,9 @@ func (j jsonArrivalDepthDurationMultiHazardProvider) Hazard(l geography.Location
9393
}
9494
var h hazards.HazardEvent
9595
h, err = j.process(hd, h)
96+
if err != nil {
97+
panic(err)
98+
}
9699
hm.Append(h.(hazards.ArrivalDepthandDurationEvent))
97100
}
98101
return &hm, nil

structures/structure.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,11 +471,7 @@ func computeConsequencesMulti(events []hazards.HazardEvent, s StructureDetermini
471471
}
472472

473473
func computeConsequencesMultiHazard(event hazards.MultiHazardEvent, s StructureDeterministic) (consequences.Result, error) {
474-
// this function needs to return a single result. Not a slice of results
475-
// Make a nested Result where each column is itself a Result
476474

477-
// Rethinking the results format. The current version repeats the structure info for each result.
478-
// The main result body can include the structure info, and we can simply store the details of the iteration results in a column as json.
479475
mainHeader := []string{
480476
"fd_id", "x", "y", "damage category", "occupancy type",
481477
"pop2amu65", "pop2amo65", "pop2pmu65", "pop2pmo65", "cbfips",
@@ -677,5 +673,6 @@ func computeConsequencesMultiHazard(event hazards.MultiHazardEvent, s StructureD
677673
break
678674
}
679675
}
676+
// ret.Result[20] = fmt.Sprintf("%v", subResult) // saving the results as a string
680677
return ret, err
681678
}

0 commit comments

Comments
 (0)