diff --git a/.gitignore b/.gitignore index 8ab2149e584fa00e61611fc7e781d576cc7e048c..75ffdd60fa16c59dac9d3680f19dbfd06467902e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /node_modules /.vs *.png -*.npy \ No newline at end of file +*.npy +*.csv \ No newline at end of file diff --git a/controllers/cfsController.js b/controllers/cfsController.js new file mode 100644 index 0000000000000000000000000000000000000000..c51015f1183e1d0bc63a94f2f802aa63f1710c19 --- /dev/null +++ b/controllers/cfsController.js @@ -0,0 +1,112 @@ +cfs = require('../models/cfs.js'); +current_year = require('../models/gdd_current.js'); +utils = require('../lib/utils'); + +function find(collection, query, projection, t_base, res, product) { + current_year.find(query).limit(1).then(function(cy) { + var min_temps = cy[0]["min_temps"] + var max_temps = cy[0]["max_temps"] + + var gdd_sum_cy = 0; + + for (var i = 0; i < min_temps.length; i++) { + gdd_value = utils.calculate_gdd(min_temps[i], max_temps[i], t_base, product); + gdd_sum_cy += gdd_value + } + + collection.find(query).limit(200).then(function(data) { + // console.log(data); + var base_date = data[0]["time"] + var lat = data[0]["location"]["coordinates"][1] + var lon = data[0]["location"]["coordinates"][0] + var gdds = [] + var i = 0; + while (data[i] !== undefined) { + if (lat != data[i]["location"]["coordinates"][1] || + lon != data[i]["location"]["coordinates"][0]) { + break; + } + gdd_value = utils.calculate_gdd(data[i].min_temp, data[i].max_temp, t_base, product); + gdd_sum_cy += gdd_value + gdds.push(gdd_sum_cy) + i += 1 + } + // for (var i = 0; i < 10; i++) { + // + // } + + res.json({ + message: "CFS GDD", + data: gdds, + base_date: base_date, + closest_lon: data[0]["location"]["coordinates"][0], + closest_lat: data[0]["location"]["coordinates"][1] + }) + }, function(err) { + res.status(500).send({"internal error": err}) + }) + + }, function(err) { + res.status(500).send({"internal error": err}) + }) + +} + + +exports.cfs = function (req, res) { + var product = req.params.product; + + var latitude = parseFloat(req.body.latitude) + var longitude = parseFloat(req.body.longitude) + + var query = { + location: { + "$near": { + "$geometry": { + "type": "Point", + "coordinates": [longitude, latitude] + }, + }, + }, + } + + var projection = { + min_temp: 1, + max_temp: 1, + location: 1, + } + + var t_base = 50 + + errors = [] + + if (latitude < 24.083334 || latitude > 49.916668) { + errors.push({ + parameter_error: "latitude", + message: latitude.toString() + " is out of bounds for GDD calculations. Must be between 24.083334 - 49.916668" + }); + } + + if (req.body.hasOwnProperty("t_base")) { + t_base = parseFloat(req.body.t_base); + } else { + out = utils.product_base_switch(product, errors, t_base); + t_base = out.t_base; + errors = out.errors; + } + + if (longitude < -125 || longitude > -66.5) { + errors.push({ + parameter_error: "longitude", + message: longitude.toString() + " is out of bounds for GDD calculations. Must be between -125.0 - -66.5" + }); + } + + if (errors.length > 0) { + res.status(400).send({ + errors: errors + }) + } + + find(cfs, query, projection, t_base, res, product); +}; \ No newline at end of file diff --git a/models/cfs.js b/models/cfs.js new file mode 100644 index 0000000000000000000000000000000000000000..48453757acf8be1aa1f945b22c812cbc1a313e23 --- /dev/null +++ b/models/cfs.js @@ -0,0 +1,30 @@ +var mongoose = require('mongoose'); +//schema +var coordinatesSchema = mongoose.Schema({ + id_: { + type: String, + required: true + }, + location: { + type: { + type: String, + enum: ['Point', 'Polygon'] + }, + coordinates: [Number], + }, + max_temp: { + type: Number, + required: true + }, + min_temp: { + type: Number, + required: true + }, + time: { + type: Date, + default: Date.now + }, +}); + +var Model = module.exports = mongoose.model('cfs', coordinatesSchema, "gefs"); + diff --git a/routes.js b/routes.js index 1d5d4495146ab68de3d4d982ae7c6efed4d3b964..cf3fda3d7dea52ab95dfb7072eee80b6ee5653f0 100644 --- a/routes.js +++ b/routes.js @@ -5,10 +5,12 @@ const normController = require("./controllers/gddNormalController") const freezingDatesController = require("./controllers/freezingDatesController") const confidenceIntervalController = require("./controllers/gddConfidenceInterval") const gefsController = require("./controllers/gefsController") +const cfsController = require("./controllers/cfsController") router.route("/:product/daily/:year/accumulated").post(accController.accumulated_gdd) router.route("/:product/daily/:year").post(controller.year_gdd) router.route("/:product/gefs/accumulated").post(gefsController.gefs) +router.route("/:product/cfs/accumulated").post(cfsController.cfs) router.route("/:product/normal").post(normController.normal) router.route("/:product/confidence").post(confidenceIntervalController.confidence_interval) router.route("/:product/normal/accumulated").post(accController.accumulated_normal_gdd) diff --git a/swagger_definition.yaml b/swagger_definition.yaml index 0456d5ee50287d1031473e7300748135e41be78b..6085b65e80870eddc944157a9918bdd2073c2853 100644 --- a/swagger_definition.yaml +++ b/swagger_definition.yaml @@ -614,6 +614,94 @@ paths: minimum: -125.0 maximum: -66.5 example: -76.94 + 400: + description: Bad Request + content: + application/json: + schema: + type: object + properties: + errors: + type: array + items: + type: object + properties: + parameter_error: + type: string + example: latitude + message: + type: string + example: 22.5 is out of bounds for GDD calculations. Must be between 24.083334 - 49.916668 + /api/{product}/cfs/accumulated: + post: + summary: Returns CFS forecast GDD data + description: Returns accumulated CFS forecast GDD data for a specific product, lat, and lon + produces: + - application/json + consumes: + - application/json + parameters: + - in: path + name: product + required: true + description: Agricultural product to calculate gdd for + schema: + type: string + enum: [corn, cotton, oat, peanut, pea, potato, rice, soybean, sorghum, spring_wheat, sugar_beet, sunflower, tomato, wheat] + requestBody: + content: + application/json: + schema: + type: object + required: + - longitude + - latitude + properties: + latitude: + description: latitude to calculate gdd on + type: number + minimum: 24.083334 + maximum: 49.916668 + example: 38.99 + longitude: + description: longitude to calculate gdd on + type: number + minimum: -125.0 + maximum: -66.5 + example: -76.94 + t_base: + description: Base temperature to calculate gdd on, in fahrenheit. NOT REQUIRED + type: number + example: 50 + + responses: + 200: + description: Success + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: CFS GDD + base_date: + type: string + format: date + data: + type: array + items: + type: number + closest_lat: + type: number + minimum: 24.083334 + maximum: 49.916668 + example: 38.99 + closest_lon: + type: number + minimum: -125.0 + maximum: -66.5 + example: -76.94 400: description: Bad Request content: diff --git a/test_server.py b/test_server.py index e2919ad89d497cd8c1240d6f373753cf02ba9912..bfa6ac23319f5aced48864a43e1ecc4396249b7a 100644 --- a/test_server.py +++ b/test_server.py @@ -3,54 +3,97 @@ import os import time import matplotlib.pyplot as plt import numpy as np - +from pymongo import MongoClient +import pandas as pd data = { "latitude": 38.98567, "longitude": -76.94146 } - t = time.time() + +client = MongoClient("mongodb+srv://gdd-server:u8i3icLAJXjZEhTs@cluster0.wdxf4.mongodb.net") + +db = client["gdd_database"] +gdd = db["gdd_current"] + +query = { + "location": { + "$near": { + "$geometry": { + "type": "Point", + "coordinates": [float(data["longitude"]), float(data["latitude"])] + }, + }, + }, + } + +min_temps = [] +max_temps = [] +for loc_data in gdd.find(query).limit(1): + min_temps = loc_data["min_temps"] + max_temps = loc_data["max_temps"] + + + +crops = ["corn", "soybean", "cotton", "wheat", "oat", "potato", "rice", "pea"] + +crop_data = {} +temps = [] + +for c in crops: + print (c) + df = pd.DataFrame(columns=("min_temp", "max_temp", "gdd")) + + r = requests.post("http://localhost:4000/api/%s/daily/2021/accumulated" % c, data=data) + print (r.json()) + crop_gdd = r.json()["data"] + for mt, mat, gd in zip(min_temps, max_temps, crop_gdd): + da = {"min_temp": mt, "max_temp": mat, "gdd": gd} + df = df.append(da, ignore_index=True) + + df.to_csv("2021_%s.csv" % c) + # r = requests.post("http://localhost:4000/api/soybean/daily/1981", data=data) +# # print (r.status_code) +# # print (r.json()) +# # print (time.time() - t) +# # print () +# # r = requests.post("http://localhost:4000/api/soybean/daily/2016", data=data) +# # print (r.status_code) +# # print (r.json()) +# # print (time.time() - t) +# # print () +# r = requests.post("http://localhost:4000/api/soybean/normal", data=data) # print (r.status_code) # print (r.json()) # print (time.time() - t) # print () -# r = requests.post("http://localhost:4000/api/soybean/daily/2016", data=data) +# r = requests.post("http://localhost:4000/api/soybean/gefs", data=data) # print (r.status_code) # print (r.json()) # print (time.time() - t) -# print () -r = requests.post("http://localhost:4000/api/soybean/normal", data=data) -print (r.status_code) -print (r.json()) -print (time.time() - t) -print () -r = requests.post("http://localhost:4000/api/soybean/gefs", data=data) -print (r.status_code) -print (r.json()) -print (time.time() - t) -# r = requests.post("http://localhost:4000/api/freezing/28.2", data=data) -# print (r.status_code) -# print (r.json()) -# r = requests.post("http://localhost:4000/api/corn/confidence", data=data) -# print (r.status_code) -# print (r.json()) +# # r = requests.post("http://localhost:4000/api/freezing/28.2", data=data) +# # print (r.status_code) +# # print (r.json()) +# # r = requests.post("http://localhost:4000/api/corn/confidence", data=data) +# # print (r.status_code) +# # print (r.json()) -# min_gdds = r.json()["minimum"] -# max_gdds = r.json()["maximum"] +# # min_gdds = r.json()["minimum"] +# # max_gdds = r.json()["maximum"] -# r = requests.post("http://localhost:4000/api/corn/normal/accumulated", data=data) -# print (r.status_code) -# print (r.json()) +# # r = requests.post("http://localhost:4000/api/corn/normal/accumulated", data=data) +# # print (r.status_code) +# # print (r.json()) -# normals = r.json()["data"] +# # normals = r.json()["data"] -# # max_gdds = np.array(max_gdds) + np.array(normals) -# # max_gdds /= 2 -# # min_gdds = np.array(min_gdds) + np.array(normals) -# # min_gdds /= 2 +# # # max_gdds = np.array(max_gdds) + np.array(normals) +# # # max_gdds /= 2 +# # # min_gdds = np.array(min_gdds) + np.array(normals) +# # # min_gdds /= 2 -# plt.plot(list(range(len(normals))), normals, color="black") -# plt.plot(list(range(len(normals))), max_gdds, color="orange") -# plt.plot(list(range(len(normals))), min_gdds, color="blue") -# plt.savefig("test.png", dpi=600) \ No newline at end of file +# # plt.plot(list(range(len(normals))), normals, color="black") +# # plt.plot(list(range(len(normals))), max_gdds, color="orange") +# # plt.plot(list(range(len(normals))), min_gdds, color="blue") +# # plt.savefig("test.png", dpi=600) \ No newline at end of file