Skip to content

Commit

Permalink
Merge pull request #23 from Dewberry/feature/forcing-data-justin
Browse files Browse the repository at this point in the history
extract rating curve
  • Loading branch information
ar-siddiqui authored Jun 3, 2022
2 parents 07e8df7 + 4148fc7 commit fde03f7
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 68 deletions.
20 changes: 0 additions & 20 deletions tools/geospatial.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"math"
"path/filepath"
"regexp"
"strconv"
"strings"

"github.com/USACE/filestore"
Expand Down Expand Up @@ -64,25 +63,6 @@ func checkUnitConsistency(modelUnits string, sourceCRS string) error {
return errors.New("Unable to check unit consistency, could not identify the coordinate reference system's units")
}

func getDataPairsfromTextBlock(nDataPairsLine string, sc *bufio.Scanner, colWidth int, valueWidth int) ([][2]float64, error) {
pairs := [][2]float64{}
for sc.Scan() {
line := sc.Text()
if strings.HasPrefix(line, nDataPairsLine) {
nPairs, err := strconv.Atoi(rightofEquals(line))
if err != nil {
return pairs, errors.Wrap(err, 0)
}
pairs, err = dataPairsfromTextBlock(sc, nPairs, colWidth, valueWidth)
if err != nil {
return pairs, errors.Wrap(err, 0)
}
break
}
}
return pairs, nil
}

// distance returns the distance along a straight line in euclidean space
func distance(p0, p1 [2]float64) float64 {
result := math.Sqrt(math.Pow((p1[0]-p0[0]), 2) + math.Pow((p1[1]-p0[1]), 2))
Expand Down
164 changes: 116 additions & 48 deletions tools/unsteady.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,96 @@ func parseBCHeader(line string) (parentType string, parent string, flowEndRS str
return
}

// Return a RatingCurve object, bool skipScan, error encountered
func getRatingCurveData(sc *bufio.Scanner) (RatingCurve, bool, error) {
rc := RatingCurve{}

series, innerErr := getDataPairsfromTextBlock("Rating Curve", sc, 80, 8)

if innerErr != nil {
return rc, false, innerErr
}
rc.Values = series

for sc.Scan() {
line := sc.Text()
loe := leftofEquals(line)

if stringInSlice(loe, forcingElementsPrefix[:]) {
return rc, true, nil
}

if strings.HasPrefix(line, "Use DSS") {
if rightofEquals(line) == "True" {
rc.UseDSS = true
}
return rc, false, nil
}
}
return rc, false, nil
}

// Return a Hydrograph object, bool skipScan, error encountered
func getHydrographData(sc *bufio.Scanner, hydrographType string, pairedData bool, flowEndRS string) (Hydrograph, bool, error) {
hg := Hydrograph{}

if flowEndRS != "" {
hg.EndRS = flowEndRS
}

if pairedData { // Stage and Flow Hydrograph
series, innerErr := getDataPairsfromTextBlock(hydrographType, sc, 80, 8)

if innerErr != nil {
return hg, false, innerErr
}
hg.Values = series
} else {
numVals, innerErr := strconv.Atoi(strings.TrimSpace(rightofEquals(sc.Text())))
if innerErr != nil {
return hg, false, innerErr
}

series, innerErr := seriesFromTextBlock(sc, numVals, 80, 8)

if innerErr != nil {
return hg, false, innerErr
}
hg.Values = series
}

for sc.Scan() {
line := sc.Text()
loe := leftofEquals(line)

if stringInSlice(loe, forcingElementsPrefix[:]) {
return hg, true, nil
}

switch loe {
case "Use DSS":
if rightofEquals(line) == "True" {
hg.UseDSS = true
}

case "Use Fixed Start Time":
ufs := strings.TrimSpace(rightofEquals(line))
if ufs == "True" {
hg.UseFixedStart = true
}
case "Fixed Start Date/Time":
fsdt := strings.Split(rightofEquals(sc.Text()), ",")
if len(fsdt[0]) > 0 {
hg.FixedStartDateTime = &DateTime{}
hg.FixedStartDateTime.Date = fsdt[0]
hg.FixedStartDateTime.Hours = fsdt[1]
}
}
}

return hg, true, nil
}

// Get Boundary Condition's data.
// Advances the given scanner.
// Returns if new RAS element is encountered or all necessary data is obtained.
Expand All @@ -68,11 +158,6 @@ func getBoundaryCondition(sc *bufio.Scanner) (parentType string, parent string,
return
}

hg := Hydrograph{}
if flowEndRS != "" {
hg.EndRS = flowEndRS
}

// Get type and data of boundary condition
for sc.Scan() {
line := sc.Text()
Expand All @@ -82,71 +167,54 @@ func getBoundaryCondition(sc *bufio.Scanner) (parentType string, parent string,
return
}

// findout type of BC
switch loe {
case "Friction Slope":
bc.Type = "Normal Depth"
slope, _ := parseFloat(strings.TrimSpace(strings.Split(rightofEquals(line), ",")[0]), 64)
bc.Data = map[string]float64{"Friction Slope": slope}
return
case "Interval":
hg.TimeInterval = rightofEquals(sc.Text())
// case "Interval":
// hg.TimeInterval = rightofEquals(sc.Text())
case "Flow Hydrograph", "Precipitation Hydrograph", "Uniform Lateral Inflow Hydrograph", "Lateral Inflow Hydrograph", "Ground Water Interflow", "Stage Hydrograph":
bc.Type = loe
bc.Data = &hg
numVals, innerErr := strconv.Atoi(strings.TrimSpace(rightofEquals(line)))
if innerErr != nil {
err = innerErr
return
}
if numVals == 0 {
break
}
series, innerErr := seriesFromTextBlock(sc, numVals, 80, 8)
hg, ss, innerErr := getHydrographData(sc, loe, false, flowEndRS)
skipScan = ss
if innerErr != nil {
err = innerErr
return
}
hg.Values = series
bc.Data = hg
return

case "Stage and Flow Hydrograph":
bc.Type = loe
numPairs, innerErr := strconv.Atoi(strings.TrimSpace(rightofEquals(line)))
if innerErr != nil {
hg, ss, innerErr := getHydrographData(sc, loe, true, flowEndRS)
skipScan = ss

if err != nil {
err = innerErr
return
}
if numPairs == 0 {
break
}
series, innerErr := dataPairsfromTextBlock(sc, numPairs, 80, 8)
bc.Data = hg
return

case "Rating Curve":
rc, ss, innerErr := getRatingCurveData(sc)
skipScan = ss

if innerErr != nil {
err = innerErr
return
}
hg.Values = series
case "Rating Curve":
bc.Type = loe

case "Use DSS":
udss := strings.TrimSpace(rightofEquals(line))
if udss == "True" {
hg.UseDSS = true
}
case "Use Fixed Start Time":
ufs := strings.TrimSpace(rightofEquals(line))
if ufs == "True" {
hg.UseFixedStart = true
}
case "Fixed Start Date/Time":
fsdt := strings.Split(rightofEquals(sc.Text()), ",")
if len(fsdt[0]) > 0 {
hg.FixedStartDateTime = &DateTime{}
hg.FixedStartDateTime.Date = fsdt[0]
hg.FixedStartDateTime.Hours = fsdt[1]
}
bc.Data = rc
bc.Type = loe
return
}
}

return parentType, parent, bc, false, nil
return
}

// Get Forcing Data from unsteady flow file.
Expand All @@ -172,9 +240,9 @@ func getUnsteadyData(fd *ForcingData, fs filestore.FileStore, flowFilePath strin
if err := sc.Err(); err != nil {
return err
}
skipScan := false

for eof == false {
for !eof {
skipScan := false
line := sc.Text()

switch {
Expand All @@ -198,7 +266,7 @@ func getUnsteadyData(fd *ForcingData, fs filestore.FileStore, flowFilePath strin
}

// if a new RAS element is encountered during the functions call, scanning again will skip that element, therefore skip scan
if skipScan == false {
if !skipScan {
eof = !sc.Scan()
if err := sc.Err(); err != nil {
return err
Expand Down
27 changes: 27 additions & 0 deletions tools/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,30 @@ out:
}
return pairs, nil
}

// Returns a paired data series.
// Gets data from next Paired Data Block encountered in HEC-RAS files.
// Returns at the successful parsing or at the end of the file.
func getDataPairsfromTextBlock(nDataPairsLine string, sc *bufio.Scanner, colWidth int, valueWidth int) ([][2]float64, error) {
pairs := [][2]float64{}
for {
line := sc.Text()
if strings.HasPrefix(line, nDataPairsLine) {
nPairs, err := strconv.Atoi(rightofEquals(line))
if err != nil {
return pairs, errors.Wrap(err, 0)
}
pairs, err = dataPairsfromTextBlock(sc, nPairs, colWidth, valueWidth)
if err != nil {
return pairs, errors.Wrap(err, 0)
}
break
}
if !sc.Scan() {
break
}

// to do: there should be a check here to see it has not enocuntered new element
}
return pairs, nil
}

0 comments on commit fde03f7

Please sign in to comment.