Esempio n. 1
0
        /// <summary>
        /// Checks the data endpoints for the Sub-Surface Flow component.
        /// </summary>
        /// <returns></returns>
        public static async Task <Dictionary <string, Dictionary <string, string> > > CheckSubsurfaceEndpoints()
        {
            Dictionary <string, Dictionary <string, string> > endpoints = new Dictionary <string, Dictionary <string, string> >();
            List <SubSurfaceFlow.SubSurfaceFlow> subsurfaces            = new List <SubSurfaceFlow.SubSurfaceFlow>();
            List <string> sources = new List <string>()
            {
                "nldas", "gldas"
            };
            ITimeSeriesInput testInput = new TimeSeriesInput()
            {
                Source       = "nldas",
                DateTimeSpan = new DateTimeSpan()
                {
                    StartDate = new DateTime(2005, 01, 01),
                    EndDate   = new DateTime(2005, 01, 05)
                },
                Geometry = new TimeSeriesGeometry()
                {
                    Point = new PointCoordinate()
                    {
                        Latitude  = 33.925673,
                        Longitude = -83.355723
                    },
                    GeometryMetadata = new Dictionary <string, string>()
                }
            };
            ITimeSeriesInputFactory iFactory = new TimeSeriesInputFactory();

            foreach (string source in sources)
            {
                SubSurfaceFlow.SubSurfaceFlow subsurface = new SubSurfaceFlow.SubSurfaceFlow();
                testInput.Source = source;
                subsurface.Input = iFactory.SetTimeSeriesInput(testInput, new List <string>()
                {
                    "subsurfaceflow"
                }, out string errorMsg);
                subsurfaces.Add(subsurface);
            }

            Parallel.ForEach(subsurfaces, (SubSurfaceFlow.SubSurfaceFlow subsurface) =>
            {
                endpoints.Add(subsurface.Input.Source, subsurface.CheckEndpointStatus());
            });
            return(endpoints);
        }
Esempio n. 2
0
        /// <summary>
        /// Gets subsurfaceflow data using the given TimeSeriesInput parameters.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ITimeSeriesOutput GetSubSurfaceFlow(ITimeSeriesInput input)
        {
            string errorMsg = "";

            // Constructs default error output object containing error message.
            Utilities.ErrorOutput err = new Utilities.ErrorOutput();

            // Validate subsurfaceflow sources.
            errorMsg = (!Enum.TryParse(input.Source, true, out SSFlowSources pSource)) ? "ERROR: 'Source' was not found or is invalid." : "";
            if (errorMsg.Contains("ERROR"))
            {
                return(err.ReturnError(errorMsg));
            }

            // SubSurfaceFlow object
            SubSurfaceFlow.SubSurfaceFlow evapo = new SubSurfaceFlow.SubSurfaceFlow();

            // ITimeSeriesInputFactory object used to validate and initialize all variables of the input object.
            ITimeSeriesInputFactory iFactory = new TimeSeriesInputFactory();

            evapo.Input = iFactory.SetTimeSeriesInput(input, new List <string>()
            {
                "BASEFLOW"
            }, out errorMsg);

            // If error occurs in input validation and setup, errorMsg is added to metadata of an empty object.
            if (errorMsg.Contains("ERROR"))
            {
                return(err.ReturnError(errorMsg));
            }

            // Gets the SubSurfaceFlow data.
            ITimeSeriesOutput result = evapo.GetData(out errorMsg);

            if (errorMsg.Contains("ERROR"))
            {
                return(err.ReturnError(errorMsg));
            }

            return(result);
        }
Esempio n. 3
0
        /// <summary>
        /// Default function for retrieving Total Flow data
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task <ITimeSeriesOutput> GetTotalFlowData(TotalFlowInput input)
        {
            //TODO: Extract the geometry percentage from following code and place in Utility class, for possible use by all controllers.

            // Steps:
            // 1 - determine geometry
            // type case ID: is equal to "huc", "commid", or "catchmentid"
            // type case ID action: send request to HMS-GIS /rest/catchment?source=SOURCE%type=TYPE%id=ID for geometry
            // type case geojson: is equal to "catchment", or "flowline"
            // type case geojson action: send request to HMS-GIS /rest/catchment/geojson/ (geojson in body) OR
            //                         : send request to HMS-GIS /rest/catchment/flowlines/ (flowline geojson in body)
            // type case points: is equal to "points"
            // type case points action: if request is one point - send request to EPA waters for watershed geometry, if request is two points
            // 2 - retrieve catchments-points table
            // 3 - collect all points catchment table (this resolves issue of possible duplicate calls on catchment edge)
            // 4 - retrieve data for all points in catchment table [Parallel]
            // 5 - iterate through catchments and assign data to appropriate catchment
            // 6 - aggregate the data for each catchment based upon how much area that cell has in the catchment [Parallel]
            // 7 - return aggregated data as a timeseries in the form of { datetime : [ catchment1, catchment2, catchment3, ... ]}
            // 8 - set metadata (request inputs, catchment data, aggregation data, output structure)
            // 9 - return output
            string error = "";

            Utilities.ErrorOutput err = new Utilities.ErrorOutput();
            GeometryResponse      geo = new GeometryResponse();

            string requestUrl = this.baseUrl + "/hms/rest/api/v2/hms/gis/percentage/";

            if (input.GeometryInputs != null)
            {
                if (input.GeometryInputs.ContainsKey("huc8") && input.GeometryInputs.ContainsKey("commid"))
                {
                    Dictionary <string, string> taskID;
                    string queryUrl = requestUrl + "?huc_8_num=" + input.GeometryInputs["huc8"] + "&com_id_num=" + input.GeometryInputs["commid"];
                    using (var httpClientHandler = new HttpClientHandler())
                    {
                        httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return(true); };
                        using (var client = new HttpClient(httpClientHandler))
                        {
                            taskID = JsonConvert.DeserializeObject <Dictionary <string, string> >(client.GetStringAsync(queryUrl).Result);
                        }
                        geo = this.RequestData(taskID["job_id"], out error);
                    }
                }
                else
                {
                    return(err.ReturnError("Input error - GeometryInputs provided is invalid."));
                }
            }
            else
            {
                switch (input.GeometryType.ToLower())
                {
                case "huc":
                    // use case 1
                    // use case 2
                    string hucID = input.GeometryInput;
                    using (var client = new HttpClient())
                    {
                        string queryUrl = baseUrl + "?huc_8_id=" + hucID;
                        client.Timeout = TimeSpan.FromMinutes(10);
                        geo            = JsonConvert.DeserializeObject <GeometryResponse>(client.GetStringAsync(queryUrl).Result);
                    }
                    //goto default;
                    break;

                case "commid":
                    // use case 3
                    //string commid = input.GeometryInput;
                    //using (var client = new HttpClient())
                    //{
                    //    string queryUrl = baseUrl + "?com_id=" + commid;
                    //    client.Timeout = TimeSpan.FromMinutes(10);
                    //    geo = JsonConvert.DeserializeObject<GeometryResponse>(client.GetStringAsync(queryUrl).Result);
                    //}
                    goto default;
                    break;

                case "catchmentid":
                    // use case 3
                    // string catchmentID = input.GeometryInput;
                    //using (var client = new HttpClient())
                    //{
                    //    geo = JsonConvert.DeserializeObject<GeometryResponse>(client.GetStringAsync(baseUrl + "/api/GridCell/catchmentid/" + catchmentID).Result);
                    //}
                    goto default;
                    break;

                case "catchment":
                    // use case 4
                    // Use POST call with geometry
                    goto default;
                    break;

                case "flowline":
                    // use case 5
                    // Use POST call with geometry
                    goto default;
                    break;

                case "points":
                    // use case 6
                    // use case 7
                    // GET call with points, hms-gis will get geometries
                    goto default;
                    break;

                case "test":
                    string testGeometry = "{\"geometry\":{\"9311911\": { \"points\": [ { \"cellArea\": 0.015624999999992895,  \"containedArea\": 4.178630503273804e-05,  \"longitude\": -71.43749999999996,  \"latitude\": 44.18749999999999,  \"percentArea\": 0.26743235220964506 },  { \"cellArea\": 0.015624999999996447,  \"containedArea\": 0.005083393397351494,  \"longitude\": -71.31249999999997,  \"latitude\": 44.18750000000001,  \"percentArea\": 32.53371774305696 },  { \"cellArea\": 0.015624999999996447,  \"containedArea\": 0.0002419268603100419,  \"longitude\": -71.31249999999997,  \"latitude\": 44.31249999999997,  \"percentArea\": 1.5483319059846201 } ] } },  \"metadata\": { \"execution time\": 86.99717831611633,  \"nldas source\": \"https://ldas.gsfc.nasa.gov/nldas/gis/NLDAS_Grid_Reference.zip\",  \"number of points\": 3,  \"request date\": \"Thu, 22 Mar 2018 11:46:44 GMT\",  \"shapefile source\": \"ftp://newftp.epa.gov/exposure/BasinsData/NHDPlus21/NHDPlus01060002.zip\" } }";
                    //string testGeometry = "{\"Geometry\": {\"02080107\": [{\"Latitude\": 37.437499999999972,\"Longitude\": -76.687499999999972,\"CellArea\": 0.0156250000000036,\"ContainedArea\": 0.00559514073505796,\"PercentArea\": 35.8089007043628},{\"Latitude\": 37.437499999999972,\"Longitude\": -76.5625,\"CellArea\": 0.0156250000000053,\"ContainedArea\": 0.0100796700330301,\"PercentArea\": 64.5098882113707},{\"Latitude\": 37.437499999999972,\"Longitude\": -76.437499999999972,\"CellArea\": 0.0156250000000142,\"ContainedArea\": 0.00780989236262298,\"PercentArea\": 49.9833111207416},{\"Latitude\": 37.437499999999972,\"Longitude\": -76.312499999999957,\"CellArea\": 0.0156250000000036,\"ContainedArea\": 0.0012605882348706,\"PercentArea\": 8.06776470316997}]},\"Metadata\": {}}";
                    geo = JsonConvert.DeserializeObject <GeometryResponse>(testGeometry);
                    break;

                default:
                    return(err.ReturnError("Input error - GeometryType provided is invalid. Provided value = " + input.GeometryType));
                }
            }
            // Check for any errors
            if (!String.IsNullOrWhiteSpace(error) || !geo.status.Equals("SUCCESS"))
            {
                return(err.ReturnError(error));
            }

            // Collect all unique points in Catchment
            List <GeometryPoint> points    = new List <GeometryPoint>();
            List <string>        pointsSTR = new List <string>();

            foreach (KeyValuePair <string, Catchment> k in geo.data.geometry)
            {
                foreach (Point cp in k.Value.points)
                {
                    GeometryPoint p = new GeometryPoint();
                    p.Latitude  = cp.latitude;
                    p.Longitude = cp.longitude;
                    if (!points.Contains(p))
                    {
                        points.Add(p);
                        pointsSTR.Add("[" + p.Latitude.ToString() + ", " + p.Longitude.ToString() + "]");
                    }
                }
            }

            ITimeSeriesInputFactory inputFactory  = new TimeSeriesInputFactory();
            List <string>           errorMessages = new List <string>();
            string errorMsg = "";
            // Initialize all surface and subsurface points
            Dictionary <string, SurfaceRunoff.SurfaceRunoff>   surfaceFlow    = new Dictionary <string, SurfaceRunoff.SurfaceRunoff>();
            Dictionary <string, SubSurfaceFlow.SubSurfaceFlow> subsurfaceFlow = new Dictionary <string, SubSurfaceFlow.SubSurfaceFlow>();

            foreach (GeometryPoint point in points)
            {
                string             key        = point.Latitude.ToString() + "," + point.Longitude.ToString();
                TimeSeriesGeometry tsGeometry = new TimeSeriesGeometry();
                tsGeometry.Point = new PointCoordinate()
                {
                    Latitude  = point.Latitude,
                    Longitude = point.Longitude
                };

                // Initialize surfaceFlow catchment point object
                errorMsg = "";
                TimeSeriesInput surfaceTempInput = new TimeSeriesInput();
                surfaceTempInput          = input;
                surfaceTempInput.Geometry = tsGeometry;
                SurfaceRunoff.SurfaceRunoff sFlow = new SurfaceRunoff.SurfaceRunoff();
                sFlow.Input = inputFactory.SetTimeSeriesInput(surfaceTempInput, new List <string>()
                {
                    "surfacerunoff"
                }, out errorMsg);
                surfaceFlow.Add(key, sFlow);
                errorMessages.Add(errorMsg);

                // Initialize subsurfaceFlow catchment point object
                errorMsg = "";
                TimeSeriesInput subSurfaceTempInput = new TimeSeriesInput();
                subSurfaceTempInput          = input;
                subSurfaceTempInput.Geometry = tsGeometry;
                SubSurfaceFlow.SubSurfaceFlow subFlow = new SubSurfaceFlow.SubSurfaceFlow();
                subFlow.Input = inputFactory.SetTimeSeriesInput(subSurfaceTempInput, new List <string>()
                {
                    "subsurfaceflow"
                }, out errorMsg);
                subsurfaceFlow.Add(key, subFlow);
                errorMessages.Add(errorMsg);
            }

            // TODO: merge parallelized calls to surfaceRunoff and subsurfaceFlow
            // Parallelized surfaceRunoff
            object        outputListLock = new object();
            List <string> surfaceError   = new List <string>();
            var           options        = new ParallelOptions {
                MaxDegreeOfParallelism = -1
            };

            Parallel.ForEach(surfaceFlow, options, (KeyValuePair <string, SurfaceRunoff.SurfaceRunoff> surF) =>
            {
                string errorM = "";
                surF.Value.GetData(out errorM);
                lock (outputListLock)
                {
                    surfaceError.Add(errorM);
                }
            });

            // Parallelized subsurfaceFlow
            List <string> subsurfaceError = new List <string>();

            Parallel.ForEach(subsurfaceFlow, options, (KeyValuePair <string, SubSurfaceFlow.SubSurfaceFlow> subF) =>
            {
                string errorM = "";
                subF.Value.GetData(out errorM);
                lock (outputListLock)
                {
                    subsurfaceError.Add(errorM);
                }
            });

            ITimeSeriesOutputFactory outputFactory = new TimeSeriesOutputFactory();
            ITimeSeriesOutput        output        = outputFactory.Initialize();

            // Aggregate catchments
            List <ITimeSeriesOutput> catchmentFlow = new List <ITimeSeriesOutput>();
            ITimeSeriesOutput        iOutput       = outputFactory.Initialize();
            var options2 = new ParallelOptions {
                MaxDegreeOfParallelism = 1
            };
            Dictionary <string, string> catchmentMeta = new Dictionary <string, string>();

            Parallel.ForEach(geo.data.geometry, options2, (KeyValuePair <string, Catchment> catchments) => {
                string catchmentID = catchments.Key;
                List <ITimeSeriesOutput> catchmentPoints = new List <ITimeSeriesOutput>();
                foreach (Point cp in catchments.Value.points)
                {
                    IPointCoordinate point = new PointCoordinate()
                    {
                        Latitude  = cp.latitude,
                        Longitude = cp.longitude
                    };
                    string key = point.Latitude.ToString() + "," + point.Longitude.ToString();
                    ITimeSeriesOutput output1 = Utilities.Merger.ModifyTimeSeries(surfaceFlow[key].Output, cp.percentArea / 100);
                    ITimeSeriesOutput output2 = Utilities.Merger.ModifyTimeSeries(subsurfaceFlow[key].Output, cp.percentArea / 100);

                    if (iOutput.Data.Count == 0)
                    {
                        iOutput = output1;
                        iOutput = Utilities.Merger.MergeTimeSeries(iOutput, output2);
                    }
                    else
                    {
                        iOutput = Utilities.Merger.MergeTimeSeries(iOutput, output1);
                        iOutput = Utilities.Merger.MergeTimeSeries(iOutput, output2);
                    }
                    catchmentPoints.Add(Utilities.Merger.AddTimeSeries(output1, output2, "TotalFlow"));
                }

                output.Data          = (Utilities.Merger.MergeTimeSeries(catchmentPoints).Data);
                int currentCatchment = catchmentMeta.Count + 1;
                catchmentMeta.Add("catchment_column_" + currentCatchment.ToString() + "_ID", catchments.Key);
            });
            // Testing
            // output.Data = iOutput.Data;

            output.DataSource = input.Source;
            output.Dataset    = "Total Flow";

            output.Metadata = surfaceFlow.First().Value.Output.Metadata;
            output.Metadata.Remove(input.Source + "_lat");
            output.Metadata.Remove(input.Source + "_lon");
            output.Metadata.Remove(input.Source + "_prod_name");
            output.Metadata.Remove(input.Source + "_param_short_name");
            output.Metadata.Remove(input.Source + "_param_name");
            output.Metadata[input.Source + "_points"] = string.Join(", ", pointsSTR);

            // Adding geometry metadata to output metadata
            foreach (KeyValuePair <string, string> kv in geo.data.metadata)
            {
                if (!output.Metadata.ContainsKey(kv.Key))
                {
                    output.Metadata.Add(kv.Key, kv.Value);
                }
            }

            // Cleaning up output metadata
            Dictionary <string, string> cleanedMetaData = new Dictionary <string, string>();

            foreach (KeyValuePair <string, string> kv in output.Metadata)
            {
                if (!kv.Key.Contains("column"))
                {
                    cleanedMetaData.Add(kv.Key, kv.Value);
                }
            }
            output.Metadata = cleanedMetaData;

            // Add catchments metadata to output metadata
            foreach (KeyValuePair <string, string> kv in catchmentMeta)
            {
                output.Metadata.Add(kv.Key, kv.Value);
            }

            return(output);
        }