From 537e66a3a309207d5cb9b00f96c70484f70fdcd2 Mon Sep 17 00:00:00 2001 From: Tucker Siegel <tgsiegel@terpmail.umd.edu> Date: Sat, 3 Dec 2022 00:25:16 -0500 Subject: [PATCH] hopefully this works --- services/forecast_service.go | 4 +- services/maturity_service.go | 380 +++++++++++++++++------------------ 2 files changed, 192 insertions(+), 192 deletions(-) diff --git a/services/forecast_service.go b/services/forecast_service.go index c59b95b..e5ff8ef 100644 --- a/services/forecast_service.go +++ b/services/forecast_service.go @@ -103,7 +103,7 @@ func forecast(ctx common.DawnCtx, gddReq models.GddRequest, plantdate time.Time, alpha := 1.0 binCount := 5 product := enums.GetProductFromString(gddReq.Product) - start := plantdate.YearDay() + start := plantdate.YearDay() - 1 if plantdate.Year()%4 == 0 && plantdate.Year()%100 != 0 || plantdate.Year()%400 == 0 { start -= 1 } @@ -246,7 +246,7 @@ func comparisonNormals(request models.GddRequest, plantdate time.Time, matches m keys := getMatchKeys(matches) lastDist := matches[keys[currentMatch]] - start := plantdate.YearDay() + start := plantdate.YearDay() - 1 year := plantdate.Year() if year%4 == 0 && year%100 != 0 || year%400 == 0 { start -= 1 diff --git a/services/maturity_service.go b/services/maturity_service.go index 5f0e959..eebd1d5 100644 --- a/services/maturity_service.go +++ b/services/maturity_service.go @@ -1,190 +1,190 @@ -package services - -import ( - "encoding/json" - "fmt" - "io" - "io/ioutil" - "math" - "math/rand" - "os" - "os/exec" - "strconv" - "strings" - "time" - - "github.com/tgs266/dawn-go-common/common" - "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/config" - "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/models" - "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/models/enums" - "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/persistence" - "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/persistence/entities" - "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/utils" -) - -type CornMaturityConfig struct { - PlantDate int `json:"plant_date"` - Tmins []float64 `json:"tmins"` - Tmaxs []float64 `json:"tmaxs"` - Srads []float64 `json:"srads"` - Units string `json:"units"` -} - -func GetCultivars(ctx common.DawnCtx, request models.CultivarRequest) models.CultivarResponse { - if request.Name != "" { - elem := persistence.FindCultivarByName(request.Name) - cultivar := models.CreateCultivar(elem) - return models.CultivarResponse{ - Cultivars: []models.Cultivar{cultivar}, - } - } else { - elems := persistence.FindCultivarsByName() - var cultivars []models.Cultivar - for _, e := range elems { - cultivars = append(cultivars, models.CreateCultivar(e)) - } - return models.CultivarResponse{ - Cultivars: cultivars, - } - } -} - -func getFullYearData(ctx common.DawnCtx, latitude float64, longitude float64, plantDate time.Time) CornMaturityConfig { - location := entities.Location{ - Type: "Point", - Coordinates: []float64{longitude, latitude}, - } - - observed := persistence.CurrentGddFindFirstByYearAndLocation(ctx, location) - predicted := persistence.CfsFindAllByLocation(location) - - tmins := append(observed.MaxTemps, predicted.MaxTemps...) - tmaxs := append(observed.MinTemps, predicted.MinTemps...) - srads := append(observed.SRAD, predicted.Srad...) - - pd := plantDate.YearDay() - - if plantDate.Year()%4 == 0 && plantDate.Year()%100 != 0 || plantDate.Year()%400 == 0 { - pd -= 1 - } - - return CornMaturityConfig{ - PlantDate: pd, - Tmins: tmins, - Tmaxs: tmaxs, - Srads: srads, - Units: "F", - } -} - -func CalculateMaturity(ctx common.DawnCtx, request models.CornMaturityRequest) models.CornMaturityResponse { - - cfg := getFullYearData(ctx, request.Latitude, request.Longitude, request.PlantDate) - fileId := rand.Intn(99-10) + 10 - - file, _ := json.MarshalIndent(cfg, "", " ") - - _ = ioutil.WriteFile("lib/maize/"+strconv.Itoa(fileId)+".json", file, 0644) - - original, err := os.Open("lib/maize/DSSAT.INP") - if err != nil { - panic(err) - } - new, err := os.Create("lib/maize/DSSAT" + strconv.Itoa(fileId) + ".INP") - if err != nil { - panic(err) - } - _, err = io.Copy(new, original) - if err != nil { - panic(err) - } - new.Close() - original.Close() - - f, err := os.OpenFile("lib/maize/DSSAT"+strconv.Itoa(fileId)+".INP", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - panic(err) - } - cultivarLineStart := fmt.Sprintf("%s %s", - request.VarNum, - request.VarName, - ) - // ECONUM + ... MUST START AFTER 24th CHARACTER - cultivarLineStart += strings.Repeat(" ", 24-len(cultivarLineStart)) - cultivarLineEnd := fmt.Sprintf("%s %s %s %s %s %s %s", - request.EcoNum, - fmt.Sprintf("%f", request.P1)[:5], - fmt.Sprintf("%f", request.P2)[:5], - fmt.Sprintf("%f", request.P5)[:5], - fmt.Sprintf("%f", request.G2)[:5], - fmt.Sprintf("%f", request.G3)[:5], - fmt.Sprintf("%f", request.PHINT)[:5], - ) - - cultivarLine := cultivarLineStart + cultivarLineEnd - if _, err = f.WriteString(cultivarLine); err != nil { - panic(err) - } - f.Close() - - cmd := exec.Command("bash", "-c", "python3 execute.py --input "+strconv.Itoa(fileId)+".json --config "+strconv.Itoa(fileId)+" --predicted") - cmd.Dir = "./lib/maize" - out, _ := cmd.Output() - - value := strings.TrimSpace(string(out)) - if value == "-1" || strings.HasPrefix(value, "A") { - panic(config.BAD_REQUEST.AddLogDetails("Script returned: " + value)) - } - - year, _ := strconv.Atoi(value[:4]) - doy, _ := strconv.Atoi(value[4:]) - - date := time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC) - if year%4 == 0 && year%100 != 0 || year%400 == 0 { - doy -= 1 - } - date = date.AddDate(0, 0, doy) - - os.Remove("lib/maize/" + strconv.Itoa(fileId) + ".json") - os.Remove("lib/maize/DSSAT" + strconv.Itoa(fileId) + ".INP") - - return models.CornMaturityResponse{ - HarvestDate: date, - } -} - -func CalculateRMMaturity(ctx common.DawnCtx, request models.CornRMMaturityRequest) models.CornMaturityResponse { - fyData := getFullYearData(ctx, request.Latitude, request.Longitude, request.PlantDate) - gdds := utils.CalculateGddValues(fyData.Tmins, fyData.Tmaxs, enums.ProductType.CORN, false) - - start := request.PlantDate.YearDay() - year := request.PlantDate.Year() - if year%4 == 0 && year%100 != 0 || year%400 == 0 { - start -= 1 - } - - acc := 0.0 - lastAcc := 0.0 - expected := float64(((request.RelativeMaturity - 95.0) * 22.0) + 2375.0) - found := 0 - - for i := start; i < len(gdds); i++ { - lastAcc = acc - acc += gdds[i] - found = i - if math.Abs(acc-expected) > math.Abs(lastAcc-expected) { - break - } - } - - if year%4 == 0 && year%100 != 0 || year%400 == 0 { - found += 1 - } - - date := request.PlantDate.AddDate(0, 0, found-start) - - return models.CornMaturityResponse{ - HarvestDate: date, - } - -} +package services + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "math" + "math/rand" + "os" + "os/exec" + "strconv" + "strings" + "time" + + "github.com/tgs266/dawn-go-common/common" + "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/config" + "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/models" + "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/models/enums" + "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/persistence" + "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/persistence/entities" + "gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/utils" +) + +type CornMaturityConfig struct { + PlantDate int `json:"plant_date"` + Tmins []float64 `json:"tmins"` + Tmaxs []float64 `json:"tmaxs"` + Srads []float64 `json:"srads"` + Units string `json:"units"` +} + +func GetCultivars(ctx common.DawnCtx, request models.CultivarRequest) models.CultivarResponse { + if request.Name != "" { + elem := persistence.FindCultivarByName(request.Name) + cultivar := models.CreateCultivar(elem) + return models.CultivarResponse{ + Cultivars: []models.Cultivar{cultivar}, + } + } else { + elems := persistence.FindCultivarsByName() + var cultivars []models.Cultivar + for _, e := range elems { + cultivars = append(cultivars, models.CreateCultivar(e)) + } + return models.CultivarResponse{ + Cultivars: cultivars, + } + } +} + +func getFullYearData(ctx common.DawnCtx, latitude float64, longitude float64, plantDate time.Time) CornMaturityConfig { + location := entities.Location{ + Type: "Point", + Coordinates: []float64{longitude, latitude}, + } + + observed := persistence.CurrentGddFindFirstByYearAndLocation(ctx, location) + predicted := persistence.CfsFindAllByLocation(location) + + tmins := append(observed.MaxTemps, predicted.MaxTemps...) + tmaxs := append(observed.MinTemps, predicted.MinTemps...) + srads := append(observed.SRAD, predicted.Srad...) + + pd := plantDate.YearDay() - 1 + + if plantDate.Year()%4 == 0 && plantDate.Year()%100 != 0 || plantDate.Year()%400 == 0 { + pd -= 1 + } + + return CornMaturityConfig{ + PlantDate: pd, + Tmins: tmins, + Tmaxs: tmaxs, + Srads: srads, + Units: "F", + } +} + +func CalculateMaturity(ctx common.DawnCtx, request models.CornMaturityRequest) models.CornMaturityResponse { + + cfg := getFullYearData(ctx, request.Latitude, request.Longitude, request.PlantDate) + fileId := rand.Intn(99-10) + 10 + + file, _ := json.MarshalIndent(cfg, "", " ") + + _ = ioutil.WriteFile("lib/maize/"+strconv.Itoa(fileId)+".json", file, 0644) + + original, err := os.Open("lib/maize/DSSAT.INP") + if err != nil { + panic(err) + } + new, err := os.Create("lib/maize/DSSAT" + strconv.Itoa(fileId) + ".INP") + if err != nil { + panic(err) + } + _, err = io.Copy(new, original) + if err != nil { + panic(err) + } + new.Close() + original.Close() + + f, err := os.OpenFile("lib/maize/DSSAT"+strconv.Itoa(fileId)+".INP", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + panic(err) + } + cultivarLineStart := fmt.Sprintf("%s %s", + request.VarNum, + request.VarName, + ) + // ECONUM + ... MUST START AFTER 24th CHARACTER + cultivarLineStart += strings.Repeat(" ", 24-len(cultivarLineStart)) + cultivarLineEnd := fmt.Sprintf("%s %s %s %s %s %s %s", + request.EcoNum, + fmt.Sprintf("%f", request.P1)[:5], + fmt.Sprintf("%f", request.P2)[:5], + fmt.Sprintf("%f", request.P5)[:5], + fmt.Sprintf("%f", request.G2)[:5], + fmt.Sprintf("%f", request.G3)[:5], + fmt.Sprintf("%f", request.PHINT)[:5], + ) + + cultivarLine := cultivarLineStart + cultivarLineEnd + if _, err = f.WriteString(cultivarLine); err != nil { + panic(err) + } + f.Close() + + cmd := exec.Command("bash", "-c", "python3 execute.py --input "+strconv.Itoa(fileId)+".json --config "+strconv.Itoa(fileId)+" --predicted") + cmd.Dir = "./lib/maize" + out, _ := cmd.Output() + + value := strings.TrimSpace(string(out)) + if value == "-1" || strings.HasPrefix(value, "A") { + panic(config.BAD_REQUEST.AddLogDetails("Script returned: " + value)) + } + + year, _ := strconv.Atoi(value[:4]) + doy, _ := strconv.Atoi(value[4:]) + + date := time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC) + if year%4 == 0 && year%100 != 0 || year%400 == 0 { + doy -= 1 + } + date = date.AddDate(0, 0, doy) + + os.Remove("lib/maize/" + strconv.Itoa(fileId) + ".json") + os.Remove("lib/maize/DSSAT" + strconv.Itoa(fileId) + ".INP") + + return models.CornMaturityResponse{ + HarvestDate: date, + } +} + +func CalculateRMMaturity(ctx common.DawnCtx, request models.CornRMMaturityRequest) models.CornMaturityResponse { + fyData := getFullYearData(ctx, request.Latitude, request.Longitude, request.PlantDate) + gdds := utils.CalculateGddValues(fyData.Tmins, fyData.Tmaxs, enums.ProductType.CORN, false) + + start := request.PlantDate.YearDay() - 1 + year := request.PlantDate.Year() + if year%4 == 0 && year%100 != 0 || year%400 == 0 { + start -= 1 + } + + acc := 0.0 + lastAcc := 0.0 + expected := float64(((request.RelativeMaturity - 95.0) * 22.0) + 2375.0) + found := 0 + + for i := start; i < len(gdds); i++ { + lastAcc = acc + acc += gdds[i] + found = i + if math.Abs(acc-expected) > math.Abs(lastAcc-expected) { + break + } + } + + if year%4 == 0 && year%100 != 0 || year%400 == 0 { + found += 1 + } + + date := request.PlantDate.AddDate(0, 0, found-start) + + return models.CornMaturityResponse{ + HarvestDate: date, + } + +} -- GitLab