// -------------- SubSurfaceFlow Functions -------------- // /// <summary> /// Get SubSurfaceFlow data function. /// </summary> /// <param name="errorMsg"></param> /// <returns></returns> public ITimeSeriesOutput GetData(out string errorMsg) { errorMsg = ""; // If the timezone information is not provided, the tz details are retrieved and set to the geometry.timezone varaible. if (this.Input.Geometry.Timezone.Offset == 0) { Utilities.Time tz = new Utilities.Time(); this.Input.Geometry.Timezone = tz.GetTimezone(out errorMsg, this.Input.Geometry.Point) as Timezone; if (errorMsg.Contains("ERROR")) { return(null); } } //TODO: Check Source and run specific subcomponent class for source ITimeSeriesOutputFactory iFactory = new TimeSeriesOutputFactory(); this.Output = iFactory.Initialize(); switch (this.Input.Source) { case "nldas": // NLDAS SubSurfaceFlow Data call NLDAS nldas = new NLDAS(); this.Output = nldas.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; case "gldas": // GLDAS SubSurfaceFlow Data call GLDAS gldas = new GLDAS(); this.Output = gldas.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; default: errorMsg = "ERROR: 'Source' for subsurfaceflow was not found among available sources or is invalid."; break; } ; // Adds Geometry metadata to the output metadata. NOT WORKING this.Output.Metadata.Concat(this.Input.Geometry.GeometryMetadata); // Adds Timezone info to metadata this.Output.Metadata.Add(this.Input.Source + "_timeZone", this.Input.Geometry.Timezone.Name); this.Output.Metadata.Add(this.Input.Source + "_tz_offset", this.Input.Geometry.Timezone.Offset.ToString()); //TODO: Add output format control return(this.Output); }
// -------------- Evapotranspiration Functions -------------- // /// <summary> /// Get Evapotranspiration data function. /// </summary> /// <param name="errorMsg"></param> /// <returns></returns> public ITimeSeriesOutput GetData(out string errorMsg) { errorMsg = ""; // If the timezone information is not provided, the tz details are retrieved and set to the geometry.timezone varaible. if (this.Input.Geometry.Timezone.Offset == 0 && !this.Input.Source.Contains("ncdc")) //if (this.Input.Geometry.Timezone.Offset == 0) { Utilities.Time tz = new Utilities.Time(); this.Input.Geometry.Timezone = tz.GetTimezone(out errorMsg, this.Input.Geometry.Point) as Timezone; if (errorMsg.Contains("ERROR")) { return(null); } } //TODO: Check Source and run specific subcomponent class for source ITimeSeriesOutputFactory iFactory = new TimeSeriesOutputFactory(); this.Output = iFactory.Initialize(); Elevation elev = new Elevation(this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude); Utilities.Time offsets = new Utilities.Time(); //this.Algorithm = (this.Input.Source != null) ? this.Input.Source : this.Algorithm; //Error checking and data validation if (this.Input.Source != "gldas" && this.Algorithm == "gldas") { errorMsg = "ERROR: GLDAS algorithm requires GLDAS data source."; return(null); } if (this.Input.Source != "nldas" && this.Algorithm == "nldas") { errorMsg = "ERROR: NLDAS algorithm requires NLDAS data source."; return(null); } if (this.Input.Source == "daymet" && this.Algorithm != "hamon" && this.Algorithm != "mortoncrae" && this.Algorithm != "mortoncrwe" && this.Algorithm != "priestlytaylor") { errorMsg = "ERROR: Algorithm is incompatible with Daymet data source."; return(null); } if (this.Input.Source == "ncdc" && this.Algorithm != "hamon") { errorMsg = "ERROR: Algorithm is incompatible with NCDC data source."; return(null); } if ((this.Algorithm != "hamon" || this.Algorithm != "gldas") && this.Input.Source == "gldas" && (this.Input.DateTimeSpan.StartDate.Year > 2010 || this.Input.DateTimeSpan.EndDate.Year > 2010)) { errorMsg = "ERROR: No data available for the requested Source/Algorithm/Date range."; return(null); } if (this.Input.Source == "custom") { if (this.Algorithm == "penmanhourly" || this.Algorithm == "hspf") { errorMsg = "ERROR: Hourly algorithms do not yet support custom data."; return(null); } this.Input.Geometry.GeometryMetadata["userdata"] = UserData; } switch (this.Algorithm) { case "nldas": // NLDAS Evapotranspiration Data call NLDAS nldas = new NLDAS(); this.Output = nldas.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; case "gldas": // GLDAS Evapotranspiration Data call GLDAS gldas = new GLDAS(); this.Output = gldas.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; case "hamon": // Hamon Evapotranspiration Data call Hamon hamon = new Hamon(); hamon.Latitude = this.Input.Geometry.Point.Latitude; hamon.Longitude = this.Input.Geometry.Point.Longitude; this.Output = hamon.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "priestlytaylor": // Priestly Taylor Evapotranspiration Data call PriestleyTaylor priestleyTaylor = new PriestleyTaylor(); priestleyTaylor.Latitude = this.Input.Geometry.Point.Latitude; priestleyTaylor.Longitude = this.Input.Geometry.Point.Longitude; priestleyTaylor.Albedo = this.Albedo; priestleyTaylor.Elevation = elev.getElevation(out errorMsg); this.Output = priestleyTaylor.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "grangergray": // Granger Gray Evapotranspiration Data call var test = this.Input; GrangerGray grangerGray = new GrangerGray(); grangerGray.Latitude = this.Input.Geometry.Point.Latitude; grangerGray.Longitude = this.Input.Geometry.Point.Longitude; grangerGray.Albedo = this.Albedo; grangerGray.Elevation = elev.getElevation(out errorMsg); this.Output = grangerGray.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "penpan": // Penpan Evapotranspiration Data call Penpan penpan = new Penpan(); penpan.Latitude = this.Input.Geometry.Point.Latitude; penpan.Longitude = this.Input.Geometry.Point.Longitude; penpan.Albedo = this.Albedo; penpan.Elevation = elev.getElevation(out errorMsg); this.Output = penpan.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "mcjannett": // McJannett Evapotranspiration Data call McJannett mcjannett = new McJannett(); mcjannett.Latitude = this.Input.Geometry.Point.Latitude; mcjannett.Longitude = this.Input.Geometry.Point.Longitude; mcjannett.Albedo = this.Albedo; mcjannett.Elevation = elev.getElevation(out errorMsg); mcjannett.SurfaceArea = this.LakeSurfaceArea; mcjannett.LakeDepth = this.LakeDepth; mcjannett.airToWaterTempFactor[1] = Convert.ToDouble(this.AirTemperature["1"]); mcjannett.airToWaterTempFactor[2] = Convert.ToDouble(this.AirTemperature["2"]); mcjannett.airToWaterTempFactor[3] = Convert.ToDouble(this.AirTemperature["3"]); mcjannett.airToWaterTempFactor[4] = Convert.ToDouble(this.AirTemperature["4"]); mcjannett.airToWaterTempFactor[5] = Convert.ToDouble(this.AirTemperature["5"]); mcjannett.airToWaterTempFactor[6] = Convert.ToDouble(this.AirTemperature["6"]); mcjannett.airToWaterTempFactor[7] = Convert.ToDouble(this.AirTemperature["7"]); mcjannett.airToWaterTempFactor[8] = Convert.ToDouble(this.AirTemperature["8"]); mcjannett.airToWaterTempFactor[9] = Convert.ToDouble(this.AirTemperature["9"]); mcjannett.airToWaterTempFactor[10] = Convert.ToDouble(this.AirTemperature["10"]); mcjannett.airToWaterTempFactor[11] = Convert.ToDouble(this.AirTemperature["11"]); mcjannett.airToWaterTempFactor[12] = Convert.ToDouble(this.AirTemperature["12"]); this.Output = mcjannett.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "penmanopenwater": // Penman Open Water Evapotranspiration Data call PenmanOpenWater penmanOpenWater = new PenmanOpenWater(); penmanOpenWater.Latitude = this.Input.Geometry.Point.Latitude; penmanOpenWater.Longitude = this.Input.Geometry.Point.Longitude; penmanOpenWater.Albedo = this.Albedo; penmanOpenWater.Elevation = elev.getElevation(out errorMsg); this.Output = penmanOpenWater.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "penmandaily": // Penman Daily Evapotranspiration Data call PenmanDaily penmanDaily = new PenmanDaily(); penmanDaily.Latitude = this.Input.Geometry.Point.Latitude; penmanDaily.Longitude = this.Input.Geometry.Point.Longitude; penmanDaily.Albedo = this.Albedo; penmanDaily.Elevation = elev.getElevation(out errorMsg); this.Output = penmanDaily.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "penmanhourly": // Penman Hourly Evapotranspiration Data call PenmanHourly penmanHourly = new PenmanHourly(); penmanHourly.Latitude = this.Input.Geometry.Point.Latitude; penmanHourly.Longitude = this.Input.Geometry.Point.Longitude; penmanHourly.Albedo = this.Albedo; penmanHourly.Elevation = elev.getElevation(out errorMsg); penmanHourly.TimeZoneCentralLongitude = this.CentralLongitude; penmanHourly.SunAngle = this.SunAngle; this.Output = penmanHourly.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "mortoncrae": // Morton CRAE Evapotranspiration Data call MortonCRAE mortonCRAE = new MortonCRAE(); mortonCRAE.Latitude = this.Input.Geometry.Point.Latitude; mortonCRAE.Longitude = this.Input.Geometry.Point.Longitude; mortonCRAE.Albedo = this.Albedo; mortonCRAE.Elevation = elev.getElevation(out errorMsg); mortonCRAE.Emissivity = this.Emissivity; int model = Utilities.Utility.CalculateMortonMethod(this.Model); double aprecip = 0.0; mortonCRAE.AnnualPrecipitation = aprecip; this.Output = mortonCRAE.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, model, out aprecip, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "mortoncrwe": // Morton CRWE Evapotranspiration Data call MortonCRWE mortonCRWE = new MortonCRWE(); mortonCRWE.Latitude = this.Input.Geometry.Point.Latitude; mortonCRWE.Longitude = this.Input.Geometry.Point.Longitude; mortonCRWE.Albedo = this.Albedo; mortonCRWE.Elevation = elev.getElevation(out errorMsg); mortonCRWE.Emissivity = this.Emissivity; mortonCRWE.Azenith = this.Zenith; int model2 = Utilities.Utility.CalculateMortonMethod(this.Model); double aprecip2 = 0.0; mortonCRWE.AnnualPrecipitation = aprecip2; this.Output = mortonCRWE.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, model2, out aprecip2, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "shuttleworthwallace": // Shuttleworth Wallace Evapotranspiration Data call ShuttleworthWallace shuttleworthWallace = new ShuttleworthWallace(); shuttleworthWallace.Latitude = this.Input.Geometry.Point.Latitude; shuttleworthWallace.Longitude = this.Input.Geometry.Point.Longitude; shuttleworthWallace.Albedo = this.Albedo; shuttleworthWallace.Elevation = elev.getElevation(out errorMsg); shuttleworthWallace.ResistanceSurfaceSoil = this.SubsurfaceResistance; shuttleworthWallace.ResistanceStomatal = this.StomatalResistance; shuttleworthWallace.WidthLeaf = this.LeafWidth; shuttleworthWallace.GroundRoughnessLength = this.RoughnessLength; shuttleworthWallace.VegetationHeight = this.VegetationHeight; shuttleworthWallace.leafAreaIndex[1] = Convert.ToDouble(this.LeafAreaIndices["1"]); shuttleworthWallace.leafAreaIndex[2] = Convert.ToDouble(this.LeafAreaIndices["2"]); shuttleworthWallace.leafAreaIndex[3] = Convert.ToDouble(this.LeafAreaIndices["3"]); shuttleworthWallace.leafAreaIndex[4] = Convert.ToDouble(this.LeafAreaIndices["4"]); shuttleworthWallace.leafAreaIndex[5] = Convert.ToDouble(this.LeafAreaIndices["5"]); shuttleworthWallace.leafAreaIndex[6] = Convert.ToDouble(this.LeafAreaIndices["6"]); shuttleworthWallace.leafAreaIndex[7] = Convert.ToDouble(this.LeafAreaIndices["7"]); shuttleworthWallace.leafAreaIndex[8] = Convert.ToDouble(this.LeafAreaIndices["8"]); shuttleworthWallace.leafAreaIndex[9] = Convert.ToDouble(this.LeafAreaIndices["9"]); shuttleworthWallace.leafAreaIndex[10] = Convert.ToDouble(this.LeafAreaIndices["10"]); shuttleworthWallace.leafAreaIndex[11] = Convert.ToDouble(this.LeafAreaIndices["11"]); shuttleworthWallace.leafAreaIndex[12] = Convert.ToDouble(this.LeafAreaIndices["12"]); this.Output = shuttleworthWallace.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; case "hspf": // HSPF Evapotranspiration Data call HSPF hspf = new HSPF(); hspf.Latitude = this.Input.Geometry.Point.Latitude; hspf.Longitude = this.Input.Geometry.Point.Longitude; hspf.Albedo = this.Albedo; hspf.Elevation = elev.getElevation(out errorMsg); hspf.TimeZoneCentralLongitude = this.CentralLongitude; hspf.SunAngle = this.SunAngle; this.Output = hspf.Compute(this.Input, this.Output, this.Input.Geometry.Point.Latitude, this.Input.Geometry.Point.Longitude, this.Input.DateTimeSpan.StartDate.ToString(), this.Input.DateTimeSpan.EndDate.ToString(), (int)this.Input.Geometry.Timezone.Offset, out errorMsg); if (errorMsg.Contains("ERROR")) { return(null); } break; default: errorMsg = "ERROR: 'Algorithm' for evapotranspiration was not found among available sources or is invalid."; break; } ; // Adds Geometry metadata to the output metadata. NOT WORKING this.Output.Metadata.Concat(this.Input.Geometry.GeometryMetadata); // Adds Timezone info to metadata this.Output.Metadata.Add(this.Algorithm + "_timeZone", this.Input.Geometry.Timezone.Name); this.Output.Metadata.Add(this.Algorithm + "_tz_offset", this.Input.Geometry.Timezone.Offset.ToString()); //TODO: Add output format control return(this.Output); }
// -------------- Precipitation Functions -------------- // /// <summary> /// Get Precipitation data function. /// </summary> /// <param name="errorMsg"></param> /// <returns></returns> public ITimeSeriesOutput GetData(out string errorMsg) { errorMsg = ""; // If the timezone information is not provided, the tz details are retrieved and set to the geometry.timezone varaible. if (this.Input.Geometry.Timezone.Offset == 0 && !this.Input.Source.Contains("ncdc")) { Utilities.Time tz = new Utilities.Time(); this.Input.Geometry.Timezone = tz.GetTimezone(out errorMsg, this.Input.Geometry.Point) as Timezone; if (errorMsg.Contains("ERROR")) { return(null); } } //TODO: Check Source and run specific subcomponent class for source ITimeSeriesOutputFactory iFactory = new TimeSeriesOutputFactory(); this.Output = iFactory.Initialize(); switch (this.Input.Source) { case "nldas": // NLDAS Precipitation Data call NLDAS nldas = new NLDAS(); this.Output = nldas.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; case "gldas": // GLDAS Precipitation Data call GLDAS gldas = new GLDAS(); this.Output = gldas.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; case "ncdc": // NCDC Precipitation Data call NCDC ncdc = new NCDC(); this.Output = ncdc.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; case "daymet": // daymet Precipitation Data call Daymet daymet = new Daymet(); this.Output = daymet.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; case "wgen": // wgen Precipitation Data call WGEN wgen = new WGEN(); this.Output = wgen.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; case "prism": // PRISM Precipitation Data call PRISM prism = new PRISM(); this.Output = prism.GetData(out errorMsg, this.Output, this.Input); if (errorMsg.Contains("ERROR")) { return(null); } break; default: errorMsg = "ERROR: 'Source' for precipitation was not found among available sources or is invalid."; break; } ; // Adds Geometry metadata to the output metadata. NOT WORKING //this.Output.Metadata.Concat(this.Input.Geometry.GeometryMetadata); // Adds Timezone info to metadata this.Output.Metadata.Add(this.Input.Source + "_timeZone", this.Input.Geometry.Timezone.Name); this.Output.Metadata.Add(this.Input.Source + "_tz_offset", this.Input.Geometry.Timezone.Offset.ToString()); //TODO: Add output format control return(this.Output); }
/// <summary> /// Get the solar calculator data /// </summary> public void GetCalculatorData() { string errorMsg = ""; // If the timezone information is not provided, the tz details are retrieved and set to the geometry.timezone varaible. if (this.Input.Geometry.Timezone.Offset == 0) { Utilities.Time tz = new Utilities.Time(); this.Input.Geometry.Timezone = tz.GetTimezone(out errorMsg, this.Input.Geometry.Point) as Timezone; return; } ITimeSeriesOutputFactory iFactory = new TimeSeriesOutputFactory(); this.Output = iFactory.Initialize(); // Add defaults to metadata this.Output.Metadata.Add("latitude", this.Input.Geometry.Point.Latitude.ToString()); this.Output.Metadata.Add("longitude", this.Input.Geometry.Point.Longitude.ToString()); this.Output.Metadata.Add("timezone", this.Input.Geometry.Timezone.Offset.ToString()); this.Output.Metadata.Add("startDate", this.Input.DateTimeSpan.StartDate.ToString()); if (this.Model.Equals("year")) { string[] columns = new string[] { "Time (hrs past local midnight)", "Julian Day", "Julian Century", "Geom Mean Long Sun (deg)", "Geom Mean Anom Sun (deg)", "Eccent Earth Orbit", "Sun Eq of Ctr", "Sun True Long (deg)", "Sun True Anom (deg)", "Sun Rad Vector (AUs)", "Sun App Long (deg)", "Mean Obliq Ecliptic (deg)", "Obliq Corr (deg)", "Sun Rt Ascen (deg)", "Sun Declin (deg)", "vary", "Eq of Time (minutes)", "HA Sunrise (deg)", "Solar Noon (LST)", "Sunrise Time (LST)", "Sunset Time (LST)", "Sunlight Duration (minutes)", "True Solar Time (min)", "Hour Angle (deg)", "Solar Zenith Angle (deg)", "Solar Elevation Angle (deg)", "Approx Atmospheric Refraction (deg)", "Solar Elevation corrected for atm refraction (deg)", "Solar Azimuth Angle (deg cw from N)" }; this.Output.Metadata.Add("endDate", this.Input.DateTimeSpan.EndDate.ToString()); this.Output.Metadata.Add("columns", String.Join(", ", columns)); RunYearCalculation(); this.Output.Metadata.Add("localTime", this.LocalTime); this.Output.Dataset = "Solar Calculator Year"; } else { string[] columns = new string[] { "Julian Day", "Julian Century", "Geom Mean Long Sun (deg)", "Geom Mean Anom Sun (deg)", "Eccent Earth Orbit", "Sun Eq of Ctr", "Sun True Long (deg)", "Sun True Anom (deg)", "Sun Rad Vector (AUs)", "Sun App Long (deg)", "Mean Obliq Ecliptic (deg)", "Obliq Corr (deg)", "Sun Rt Ascen (deg)", "Sun Declin (deg)", "vary", "Eq of Time (minutes)", "HA Sunrise (deg)", "Solar Noon (LST)", "Sunrise Time (LST)", "Sunset Time (LST)", "Sunlight Duration (minutes)", "True Solar Time (min)", "Hour Angle (deg)", "Solar Zenith Angle (deg)", "Solar Elevation Angle (deg)", "Approx Atmospheric Refraction (deg)", "Solar Elevation corrected for atm refraction (deg)", "Solar Azimuth Angle (deg cw from N)" }; this.Output.Metadata.Add("endDate", this.Input.DateTimeSpan.EndDate.ToString()); this.Output.Metadata.Add("columns", String.Join(", ", columns)); RunDayCalculation(); this.Output.Dataset = "Solar Calculator Day"; } this.Output.DataSource = "NOAA/NASA"; this.Output.Metadata.Add("noaa_url", "https://www.esrl.noaa.gov/gmd/grad/solcalc/calcdetails.html"); this.Output.Metadata.Add("noaa_web_app", "https://www.esrl.noaa.gov/gmd/grad/solcalc/"); this.Output.Metadata.Add("description", "The calculations in the NOAA Sunrise/Sunset and Solar Position Calculators are based on equations from Astronomical Algorithms, " + "by Jean Meeus. The sunrise and sunset results are theoretically accurate to within a minute for locations between +/- 72° latitude, and within 10 minutes outside of " + "those latitudes. However, due to variations in atmospheric composition, temperature, pressure and conditions, observed values may vary from calculations."); this.Output.Metadata.Add("dataForLitigation", "The NOAA Solar Calculator is for research and recreational use only. NOAA cannot certify or authenticate sunrise, " + "sunset or solar position data. The U.S. Government does not collect observations of astronomical data, and due to atmospheric conditions our calculated " + "results may vary significantly from actual observed values."); }