-
Notifications
You must be signed in to change notification settings - Fork 12
Add reconstruction unit tests #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: reconstruction-lifecycle
Are you sure you want to change the base?
Changes from all commits
56c6014
465b359
8c156c1
7ad8877
abacef3
c7ddc10
e92de2d
7a3249f
6c5764c
1bb954d
ec0a212
8786c04
fef6b6c
f3497b2
0646fb2
8c8f1ff
f464e67
c1a5dcd
c8565d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| package hazardproviders | ||
|
|
||
| import ( | ||
| "encoding/csv" | ||
| "fmt" | ||
| "os" | ||
| "strconv" | ||
| "strings" | ||
| "time" | ||
|
|
||
| "github.com/USACE/go-consequences/geography" | ||
| "github.com/USACE/go-consequences/hazards" | ||
| ) | ||
|
|
||
| type csvArrivalDepthDurationMultiHazardProvider struct { | ||
| f *os.File | ||
| arrivals []time.Time | ||
| depths []float64 | ||
| durations []float64 | ||
| process HazardFunction | ||
| bbox geography.BBox | ||
| } | ||
|
|
||
| func InitCSV(fp string, b geography.BBox) (csvArrivalDepthDurationMultiHazardProvider, error) { | ||
| fmt.Println("Connecting to: " + fp) | ||
| file, err := os.Open(fp) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| reader := csv.NewReader(file) | ||
|
|
||
| rows, err := reader.ReadAll() | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| arrivals := make([]time.Time, len(rows)-1) | ||
| depths := make([]float64, len(rows)-1) | ||
| durations := make([]float64, len(rows)-1) | ||
|
|
||
| for i, row := range rows[1:] { | ||
| year, err := strconv.Atoi(row[2]) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| month, err := strconv.Atoi(strings.TrimSpace(row[3])) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| day, err := strconv.Atoi(strings.TrimSpace(row[4])) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| at := time.Date(year, time.Month(month), int(day), 0, 0, 0, 0, time.UTC) | ||
| depth, err := strconv.ParseFloat(row[5], 64) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| dur, err := strconv.ParseFloat(row[6], 64) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| arrivals[i] = at | ||
| depths[i] = depth | ||
| durations[i] = dur | ||
| } | ||
|
|
||
| return csvArrivalDepthDurationMultiHazardProvider{ | ||
| f: file, | ||
| arrivals: arrivals, | ||
| depths: depths, | ||
| durations: durations, | ||
| process: ArrivalDepthAndDurationHazardFunction(), | ||
| bbox: b, | ||
| }, nil | ||
|
|
||
| } | ||
|
|
||
| func (c csvArrivalDepthDurationMultiHazardProvider) Close() { | ||
| c.f.Close() | ||
| } | ||
|
|
||
| func (c csvArrivalDepthDurationMultiHazardProvider) Hazard(l geography.Location) (hazards.HazardEvent, error) { | ||
| var hm hazards.ArrivalDepthandDurationEventMulti | ||
| if c.bbox.Contains(l) { | ||
| for i, d := range c.depths { | ||
| hd := hazards.HazardData{ | ||
| Depth: d, | ||
| Velocity: 0, | ||
| ArrivalTime: c.arrivals[i], | ||
| Erosion: 0, | ||
| Duration: c.durations[i], | ||
| WaveHeight: 0, | ||
| Salinity: false, | ||
| Qualitative: "", | ||
| } | ||
| var h hazards.HazardEvent | ||
| h, err := c.process(hd, h) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| hm.Append(h.(hazards.ArrivalDepthandDurationEvent)) | ||
| } | ||
| } | ||
| return &hm, nil | ||
| } | ||
|
|
||
| func (c csvArrivalDepthDurationMultiHazardProvider) HazardBoundary() (geography.BBox, error) { | ||
| return c.bbox, nil | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package hazardproviders | ||
|
|
||
| import ( | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/USACE/go-consequences/geography" | ||
| "github.com/USACE/go-consequences/hazards" | ||
| ) | ||
|
|
||
| func TestInitCSV(t *testing.T) { | ||
| file := "/workspaces/go-consequences/data/lifecycle/test_arrival-depth-duration_hazards.csv" | ||
|
|
||
| expectedDepths := []float64{1.0, 1.0, 1.0, 2.0, 2.0} | ||
| expectedDurations := []float64{0.0, 5.0, 0.0, 0.0, 0.0} | ||
| et1 := time.Date(1984, time.Month(1), 1, 0, 0, 0, 0, time.UTC) | ||
| et2 := time.Date(1984, time.Month(1), 11, 0, 0, 0, 0, time.UTC) | ||
| et3 := time.Date(1984, time.Month(1), 21, 0, 0, 0, 0, time.UTC) | ||
| et4 := time.Date(1985, time.Month(1), 1, 0, 0, 0, 0, time.UTC) | ||
| et5 := time.Date(1985, time.Month(1), 11, 0, 0, 0, 0, time.UTC) | ||
| expectedArrivals := []time.Time{et1, et2, et3, et4, et5} | ||
|
|
||
| b := geography.BBox{ | ||
| // xMin, yMin, xMax, yMax | ||
| Bbox: []float64{-71.1, 43, -71, 43.1}, | ||
| } | ||
| ADDMHP, err := InitCSV(file, b) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| defer ADDMHP.Close() | ||
|
|
||
| loc := geography.Location{ | ||
| X: -71.05, | ||
| Y: 43.05, | ||
| SRID: "", | ||
| } | ||
|
|
||
| haz, err := ADDMHP.Hazard(loc) | ||
| h := haz.(*hazards.ArrivalDepthandDurationEventMulti) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| for { | ||
| edepth := expectedDepths[h.Index()] | ||
| edur := expectedDurations[h.Index()] | ||
| earr := expectedArrivals[h.Index()] | ||
|
|
||
| if h.Depth() != edepth { | ||
| t.Errorf("Event at index %d had Depth = %v. Expected: %3.2f", h.Index(), h.Depth(), edepth) | ||
| } | ||
| if h.Duration() != edur { | ||
| t.Errorf("Event at index %d had Duration = %v. Expected: %3.2f", h.Index(), h.Duration(), edur) | ||
| } | ||
| if h.Depth() != edepth { | ||
| t.Errorf("Event at index %d had ArrivalTime = %v. Expected: %v", h.Index(), h.ArrivalTime(), earr) | ||
| } | ||
|
|
||
| if h.HasNext() { | ||
| h.Increment() | ||
| } else { | ||
| break | ||
| } | ||
| } | ||
| } |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. huh. did you write this code? it is a pretty neat idea. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| package hazardproviders | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "os" | ||
| "time" | ||
|
|
||
| "github.com/USACE/go-consequences/geography" | ||
| "github.com/USACE/go-consequences/hazards" | ||
| ) | ||
|
|
||
| type jsonArrivalDepthDurationMultiHazardProvider struct { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. using cogs at this point is overkill |
||
| arrivals []time.Time | ||
| depthCRs []cogReader | ||
| durations []float64 | ||
| process HazardFunction | ||
| } | ||
|
|
||
| type ADDProperties struct { | ||
| Year float64 `json:"year"` | ||
| Month float64 `json:"month"` | ||
| Day float64 `json:"day"` | ||
| Depth float64 `json:"depth"` | ||
| Depthgrid string `json:"depthgrid"` | ||
| Duration float64 `json:"duration"` | ||
| Xmin float64 `json:"xmin"` | ||
| Xmax float64 `json:"xmax"` | ||
| Ymin float64 `json:"ymin"` | ||
| Ymax float64 `json:"ymax"` | ||
| } | ||
|
|
||
| type ADDEvents struct { | ||
| Events []ADDProperties `json:"events"` | ||
| } | ||
|
|
||
| func InitADDMHP(fp string) (jsonArrivalDepthDurationMultiHazardProvider, error) { | ||
| fmt.Println("Connecting to: " + fp) | ||
| c, err := os.ReadFile(fp) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| var events ADDEvents | ||
| json.Unmarshal(c, &events) | ||
|
|
||
| arrivalTimes := make([]time.Time, len(events.Events)) | ||
| durations := make([]float64, len(events.Events)) | ||
| depthCRs := make([]cogReader, len(events.Events)) | ||
|
|
||
| for i, e := range events.Events { | ||
| at := time.Date(int(e.Year), time.Month(e.Month), int(e.Day), 0, 0, 0, 0, time.UTC) | ||
| cr, err := initCR(e.Depthgrid) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| arrivalTimes[i] = at | ||
| durations[i] = e.Duration | ||
| depthCRs[i] = cr | ||
| } | ||
|
|
||
| return jsonArrivalDepthDurationMultiHazardProvider{ | ||
| arrivals: arrivalTimes, | ||
| depthCRs: depthCRs, | ||
| durations: durations, | ||
| process: ArrivalDepthAndDurationHazardFunction(), | ||
| }, nil | ||
| } | ||
|
|
||
| func (j jsonArrivalDepthDurationMultiHazardProvider) Close() { | ||
| for _, c := range j.depthCRs { | ||
| c.Close() | ||
| } | ||
| } | ||
|
|
||
| func (j jsonArrivalDepthDurationMultiHazardProvider) Hazard(l geography.Location) (hazards.HazardEvent, error) { | ||
| var hm hazards.ArrivalDepthandDurationEventMulti | ||
| for i, cr := range j.depthCRs { | ||
| d, err := cr.ProvideValue(l) | ||
| if err != nil { | ||
| return hm, err | ||
| } | ||
| hd := hazards.HazardData{ | ||
| Depth: d, | ||
| Velocity: 0, | ||
| ArrivalTime: j.arrivals[i], | ||
| Erosion: 0, | ||
| Duration: j.durations[i], | ||
| WaveHeight: 0, | ||
| Salinity: false, | ||
| Qualitative: "", | ||
| } | ||
| var h hazards.HazardEvent | ||
| h, err = j.process(hd, h) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| hm.Append(h.(hazards.ArrivalDepthandDurationEvent)) | ||
| } | ||
| return &hm, nil | ||
| } | ||
|
|
||
| func (j jsonArrivalDepthDurationMultiHazardProvider) HazardBoundary() (geography.BBox, error) { | ||
| // We'll probably want to do something different here. | ||
| // Probably allow user to define study bbox with a | ||
| // shapefile/geojson/directly entering bbox coords | ||
| return j.depthCRs[0].GetBoundingBox() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is great for now |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ismt it cool that we get such robustly different behavior out of streamabstract when we leverage the abstractions!