/// <summary>Send the DataTable to the View</summary> /// <param name="data">The data set</param> private void WriteTable(DataTable data) { // format the data into useful columns if (data != null) { int siteIdx = data.Columns.IndexOf("site"); if (siteIdx >= 0) { data.Columns.RemoveAt(siteIdx); } // modLMC - 10/03/2016 - Add the Qmax (Max Radiation) column that we require for the graphs // This is done here so that we can use the "day" or "doy" column if it exists, as it will be quicker MetUtilities.CalcQmax(data, this.weatherData.Latitude); // modLMC - 10/03/2016 - Modified to use this new function, as some data has "doy" and not "day" int dayCol = data.Columns.IndexOf("day"); int yearCol = data.Columns.IndexOf("year"); if ((yearCol >= 0) && (dayCol >= 0)) { // add a new column for the date string DataColumn dateCol = data.Columns.Add("Date", typeof(DateTime)); dateCol.SetOrdinal(0); yearCol++; // moved along dayCol++; int yr, day; // for each row in the grid for (int r = 0; r < data.Rows.Count; r++) { DateTime rowDate; try { yr = Convert.ToInt32(data.Rows[r][yearCol], CultureInfo.InvariantCulture); day = Convert.ToInt32(data.Rows[r][dayCol], CultureInfo.InvariantCulture); rowDate = new DateTime(yr, 1, 1); } catch (Exception err) { DateTime previousRowDate; if (r > 0 && DateTime.TryParse((string)data.Rows[r - 1][0], out previousRowDate)) { throw new Exception("Invalid date detected in file: " + this.weatherData.FileName + ". Previous row: " + previousRowDate.ToShortDateString() + " (day of year = " + previousRowDate.DayOfYear + ")"); } else { throw new Exception("Encountered an error while parsing date: " + err.Message); } } rowDate = rowDate.AddDays(day - 1); // calc date data.Rows[r][0] = rowDate; } if (dayCol > yearCol) { data.Columns.RemoveAt(dayCol); data.Columns.RemoveAt(yearCol); // remove unwanted columns } else { data.Columns.RemoveAt(yearCol); // remove unwanted columns data.Columns.RemoveAt(dayCol); } } this.graphMetData = data; this.weatherDataView.PopulateData(data); } }
/// <summary>User has clicked the search button.</summary> /// <param name="sender">Sender of the event.</param> /// <param name="e">Event arguments.</param> private void OnSearchClicked(object sender, EventArgs e) { try { explorerPresenter.MainPresenter.ShowWaitCursor(true); if (!string.IsNullOrEmpty(placeNameEditBox.Text) && !string.IsNullOrEmpty(countryDropDown.SelectedValue)) { if (!GetLatLongFromPlaceName()) { throw new Exception("Cannot find a latitude/longitude from the specified place name."); } } if (string.IsNullOrEmpty(latitudeEditBox.Text) || string.IsNullOrEmpty(longitudeEditBox.Text)) { throw new Exception("Must specifiy either a place name or a latitude/longitude."); } var apsoilTask = Task.Run(() => GetApsoilSoils()); var gridTask = Task.Run(() => GetGridSoils()); //var isricTask = Task.Run(() => GetISRICSoils()); // Web API no longer operational? var worldModellersTask = Task.Run(() => GetWorldModellersSoils()); var placeNameTask = Task.Run(() => GetPlacenameFromLatLong()); DataTable soilData = new DataTable(); soilData.Columns.Add("Name", typeof(string)); soilData.Columns.Add("Data source", typeof(string)); soilData.Columns.Add("Soil type", typeof(string)); soilData.Columns.Add("Distance (km)", typeof(string)); soilData.Columns.Add("PAWC for profile", typeof(string)); soilData.Columns.Add("PAWC to 300mm", typeof(string)); soilData.Columns.Add("PAWC to 600mm", typeof(string)); soilData.Columns.Add("PAWC to 1500mm", typeof(string)); Task.WaitAll(apsoilTask, gridTask, worldModellersTask, placeNameTask /*, isricTask*/); // Update the place name edit box. placeNameEditBox.Text = placeNameTask.Result; allSoils = apsoilTask.Result.Concat(gridTask.Result).Concat(worldModellersTask.Result); double[] pawcmappingLayerStructure = { 300, 300, 900 }; foreach (var soilInfo in allSoils) { var row = soilData.NewRow(); row["Name"] = soilInfo.Soil.Name; row["Data source"] = soilInfo.DataSource; row["Soil type"] = soilInfo.Soil.SoilType; row["Distance (km)"] = MetUtilities.Distance(Convert.ToDouble(latitudeEditBox.Text, System.Globalization.CultureInfo.InvariantCulture), Convert.ToDouble(longitudeEditBox.Text, System.Globalization.CultureInfo.InvariantCulture), soilInfo.Soil.Latitude, soilInfo.Soil.Longitude).ToString("F1"); var pawc = soilInfo.Soil.PAWCmm; row["PAWC for profile"] = pawc.Sum().ToString("F1"); var pawcConcentration = MathUtilities.Divide(pawc, soilInfo.Soil.Thickness); var mappedPawcConcentration = Layers.MapConcentration(pawcConcentration, soilInfo.Soil.Thickness, pawcmappingLayerStructure, 0); var mappedPawc = MathUtilities.Multiply(mappedPawcConcentration, pawcmappingLayerStructure); row["PAWC to 300mm"] = mappedPawc[0].ToString("F1"); row["PAWC to 600mm"] = (mappedPawc[0] + mappedPawc[1]).ToString("F1"); row["PAWC to 1500mm"] = mappedPawc.Sum().ToString("F1"); soilData.Rows.Add(row); } dataView.DataSource = soilData; } catch (Exception err) { explorerPresenter.MainPresenter.ShowError(err.Message); } finally { explorerPresenter.MainPresenter.ShowWaitCursor(false); } }
private void OnDoWeather(object sender, EventArgs e) { if (this.doSeek) { if (!this.OpenDataFile()) { throw new ApsimXException(this, "Cannot find weather file '" + this.FileName + "'"); } this.doSeek = false; this.reader.SeekToDate(this.clock.Today); } object[] values = this.reader.GetNextLineOfData(); if (this.clock.Today != this.reader.GetDateFromValues(values)) { throw new Exception("Non consecutive dates found in file: " + this.FileName + ". Another posibility is that you have two clock objects in your simulation, there should only be one"); } this.todaysMetData.Today = this.clock.Today; if (this.radiationIndex != -1) { this.todaysMetData.Radn = Convert.ToSingle(values[this.radiationIndex]); } else { this.todaysMetData.Radn = this.reader.ConstantAsDouble("radn"); } if (this.maximumTemperatureIndex != -1) { this.todaysMetData.Maxt = Convert.ToSingle(values[this.maximumTemperatureIndex]); } else { this.todaysMetData.Maxt = this.reader.ConstantAsDouble("maxt"); } if (this.minimumTemperatureIndex != -1) { this.todaysMetData.Mint = Convert.ToSingle(values[this.minimumTemperatureIndex]); } else { this.todaysMetData.Mint = this.reader.ConstantAsDouble("mint"); } if (this.rainIndex != -1) { this.todaysMetData.Rain = Convert.ToSingle(values[this.rainIndex]); } else { this.todaysMetData.Rain = this.reader.ConstantAsDouble("rain"); } if (this.evaporationIndex == -1) { // If Evap is not present in the weather file assign a default value this.todaysMetData.PanEvap = double.NaN; } else { this.todaysMetData.PanEvap = Convert.ToSingle(values[this.evaporationIndex]); } if (this.rainfallHoursIndex == -1) { // If Evap is not present in the weather file assign a default value this.todaysMetData.RainfallHours = double.NaN; } else { this.todaysMetData.RainfallHours = Convert.ToSingle(values[this.rainfallHoursIndex]); } if (this.vapourPressureIndex == -1) { // If VP is not present in the weather file assign a defalt value this.todaysMetData.VP = Math.Max(0, MetUtilities.svp(this.MetData.Mint)); } else { this.todaysMetData.VP = Convert.ToSingle(values[this.vapourPressureIndex]); } if (this.windIndex == -1) { // If Wind is not present in the weather file assign a default value this.todaysMetData.Wind = 3.0; } else { this.todaysMetData.Wind = Convert.ToSingle(values[this.windIndex]); } if (this.PreparingNewWeatherData != null) { this.PreparingNewWeatherData.Invoke(this, new EventArgs()); } }
private void OnDoWeather(object sender, EventArgs e) { if (this.doSeek) { if (!this.OpenDataFile()) { throw new ApsimXException(this, "Cannot find weather file '" + this.FileName + "'"); } this.doSeek = false; this.reader.SeekToDate(this.clock.Today); } object[] values = this.reader.GetNextLineOfData(); if (this.clock.Today != this.reader.GetDateFromValues(values)) { throw new Exception("Non consecutive dates found in file: " + this.FileName + ". Another posibility is that you have two clock objects in your simulation, there should only be one"); } if (this.radiationIndex != -1) { this.Radn = Convert.ToSingle(values[this.radiationIndex], CultureInfo.InvariantCulture); } else { this.Radn = this.reader.ConstantAsDouble("radn"); } if (this.maximumTemperatureIndex != -1) { this.MaxT = Convert.ToSingle(values[this.maximumTemperatureIndex], CultureInfo.InvariantCulture); } else { this.MaxT = this.reader.ConstantAsDouble("maxt"); } if (this.minimumTemperatureIndex != -1) { this.MinT = Convert.ToSingle(values[this.minimumTemperatureIndex], CultureInfo.InvariantCulture); } else { this.MinT = this.reader.ConstantAsDouble("mint"); } if (this.rainIndex != -1) { this.Rain = Convert.ToSingle(values[this.rainIndex], CultureInfo.InvariantCulture); } else { this.Rain = this.reader.ConstantAsDouble("rain"); } if (this.evaporationIndex == -1) { this.PanEvap = double.NaN; } else { this.PanEvap = Convert.ToSingle(values[this.evaporationIndex], CultureInfo.InvariantCulture); } if (this.rainfallHoursIndex == -1) { this.RainfallHours = double.NaN; } else { this.RainfallHours = Convert.ToSingle(values[this.rainfallHoursIndex], CultureInfo.InvariantCulture); } if (this.vapourPressureIndex == -1) { this.VP = Math.Max(0, MetUtilities.svp(this.MinT)); } else { this.VP = Convert.ToSingle(values[this.vapourPressureIndex], CultureInfo.InvariantCulture); } if (this.windIndex == -1) { this.Wind = 3.0; } else { this.Wind = Convert.ToSingle(values[this.windIndex], CultureInfo.InvariantCulture); } if (this.DiffuseFractionIndex == -1) { this.DiffuseFraction = -1; } else { this.DiffuseFraction = Convert.ToSingle(values[this.DiffuseFractionIndex], CultureInfo.InvariantCulture); } if (this.dayLengthIndex == -1) // Daylength is not a column - check for a constant { if (this.reader.Constant("daylength") != null) { this.DayLength = this.reader.ConstantAsDouble("daylength"); } else { this.DayLength = -1; } } else { this.DayLength = Convert.ToSingle(values[this.dayLengthIndex], CultureInfo.InvariantCulture); } if (this.PreparingNewWeatherData != null) { this.PreparingNewWeatherData.Invoke(this, new EventArgs()); } if (clock.Today.DayOfYear == WinterSolsticeDOY) { DaysSinceWinterSolstice = 0; } else { DaysSinceWinterSolstice += 1; } }
/// <summary>Method to read one days met data in from file</summary> /// <param name="date">the date to read met data</param> private DailyMetDataFromFile GetMetData(DateTime date) { if (this.doSeek) { if (!this.OpenDataFile()) { throw new ApsimXException(this, "Cannot find weather file '" + this.FileName + "'"); } this.doSeek = false; this.reader.SeekToDate(date); } object[] values; DailyMetDataFromFile readMetData = new DailyMetDataFromFile(); try { values = this.reader.GetNextLineOfData(); } catch (IndexOutOfRangeException err) { throw new Exception($"Unable to retrieve weather data on {date.ToString("yyy-MM-dd")} in file {FileName}", err); } if (date != this.reader.GetDateFromValues(values)) { throw new Exception("Non consecutive dates found in file: " + this.FileName + ". Another posibility is that you have two clock objects in your simulation, there should only be one"); } if (this.radiationIndex != -1) { readMetData.Radn = Convert.ToSingle(values[this.radiationIndex], CultureInfo.InvariantCulture); } else { readMetData.Radn = this.reader.ConstantAsDouble("radn"); } if (this.maximumTemperatureIndex != -1) { readMetData.MaxT = Convert.ToSingle(values[this.maximumTemperatureIndex], CultureInfo.InvariantCulture); } else { readMetData.MaxT = this.reader.ConstantAsDouble("maxt"); } if (this.minimumTemperatureIndex != -1) { readMetData.MinT = Convert.ToSingle(values[this.minimumTemperatureIndex], CultureInfo.InvariantCulture); } else { readMetData.MinT = this.reader.ConstantAsDouble("mint"); } if (this.rainIndex != -1) { readMetData.Rain = Convert.ToSingle(values[this.rainIndex], CultureInfo.InvariantCulture); } else { readMetData.Rain = this.reader.ConstantAsDouble("rain"); } if (this.evaporationIndex == -1) { readMetData.PanEvap = double.NaN; } else { readMetData.PanEvap = Convert.ToSingle(values[this.evaporationIndex], CultureInfo.InvariantCulture); } if (this.rainfallHoursIndex == -1) { readMetData.RainfallHours = double.NaN; } else { readMetData.RainfallHours = Convert.ToSingle(values[this.rainfallHoursIndex], CultureInfo.InvariantCulture); } if (this.vapourPressureIndex == -1) { readMetData.VP = Math.Max(0, MetUtilities.svp(readMetData.MinT)); } else { readMetData.VP = Convert.ToSingle(values[this.vapourPressureIndex], CultureInfo.InvariantCulture); } if (this.windIndex == -1) { readMetData.Wind = 3.0; } else { readMetData.Wind = Convert.ToSingle(values[this.windIndex], CultureInfo.InvariantCulture); } if (this.DiffuseFractionIndex == -1) { readMetData.DiffuseFraction = -1; } else { readMetData.DiffuseFraction = Convert.ToSingle(values[this.DiffuseFractionIndex], CultureInfo.InvariantCulture); } if (this.dayLengthIndex == -1) // Daylength is not a column - check for a constant { if (this.reader.Constant("daylength") != null) { readMetData.DayLength = this.reader.ConstantAsDouble("daylength"); } else { readMetData.DayLength = -1; } } else { readMetData.DayLength = Convert.ToSingle(values[this.dayLengthIndex], CultureInfo.InvariantCulture); } return(readMetData); }
private void OnDoWeather(object sender, EventArgs e) { if (First) { TodaysMetData = GetMetData(this.clock.Today); //Read first date to get todays data YesterdaysMetData = TodaysMetData; //Use todays Data to represent yesterday on the first day TomorrowsMetData = GetMetData(this.clock.Today.AddDays(1)); // Read another line ahead to get tomorrows data } else { // Move everything forward a day YesterdaysMetData = TodaysMetData; TodaysMetData = TomorrowsMetData; if (clock.Today == clock.EndDate && clock.EndDate == reader.LastDate) { TomorrowsMetData = TodaysMetData; } else { TomorrowsMetData = GetMetData(this.clock.Today.AddDays(1)); } } this.Radn = TodaysMetData.Radn; this.MaxT = TodaysMetData.MaxT; this.MinT = TodaysMetData.MinT; this.Rain = TodaysMetData.Rain; this.PanEvap = TodaysMetData.PanEvap; this.RainfallHours = TodaysMetData.RainfallHours; this.VP = TodaysMetData.VP; this.Wind = TodaysMetData.Wind; this.DiffuseFraction = TodaysMetData.DiffuseFraction; this.DayLength = TodaysMetData.DayLength; if (this.PreparingNewWeatherData != null) { this.PreparingNewWeatherData.Invoke(this, new EventArgs()); } if (First) { //StartDAWS = met.DaysSinceWinterSolstice; if (clock.Today.DayOfYear < WinterSolsticeDOY) { if (DateTime.IsLeapYear(clock.Today.Year - 1)) { DaysSinceWinterSolstice = 366 - WinterSolsticeDOY + clock.Today.DayOfYear; } else { DaysSinceWinterSolstice = 365 - WinterSolsticeDOY + clock.Today.DayOfYear; } } else { DaysSinceWinterSolstice = clock.Today.DayOfYear - WinterSolsticeDOY; } First = false; } if (clock.Today.DayOfYear == WinterSolsticeDOY & First == false) { DaysSinceWinterSolstice = 0; } else { DaysSinceWinterSolstice += 1; } Qmax = MetUtilities.QMax(clock.Today.DayOfYear + 1, Latitude, MetUtilities.Taz, MetUtilities.Alpha, VP); }
/// <summary>Method to read one days met data in from file</summary> /// <param name="date">the date to read met data</param> private DailyMetDataFromFile GetMetData(DateTime date) { if (this.doSeek) { if (!this.OpenDataFile()) { throw new ApsimXException(this, "Cannot find weather file '" + this.FileName + "'"); } this.doSeek = false; this.reader.SeekToDate(date); } object[] values; DailyMetDataFromFile readMetData = new DailyMetDataFromFile(); try { values = this.reader.GetNextLineOfData(); } catch (IndexOutOfRangeException err) { throw new Exception($"Unable to retrieve weather data on {date.ToString("yyy-MM-dd")} in file {FileName}", err); } if (date != this.reader.GetDateFromValues(values)) { throw new Exception("Non consecutive dates found in file: " + this.FileName + ". Another posibility is that you have two clock objects in your simulation, there should only be one"); } if (this.radiationIndex != -1) { readMetData.Radn = Convert.ToSingle(values[this.radiationIndex], CultureInfo.InvariantCulture); } else { readMetData.Radn = this.reader.ConstantAsDouble("radn"); } if (this.maximumTemperatureIndex != -1) { readMetData.MaxT = Convert.ToSingle(values[this.maximumTemperatureIndex], CultureInfo.InvariantCulture); } else { readMetData.MaxT = this.reader.ConstantAsDouble("maxt"); } if (this.minimumTemperatureIndex != -1) { readMetData.MinT = Convert.ToSingle(values[this.minimumTemperatureIndex], CultureInfo.InvariantCulture); } else { readMetData.MinT = this.reader.ConstantAsDouble("mint"); } if (this.rainIndex != -1) { readMetData.Rain = Convert.ToSingle(values[this.rainIndex], CultureInfo.InvariantCulture); } else { readMetData.Rain = this.reader.ConstantAsDouble("rain"); } if (this.evaporationIndex == -1) { readMetData.PanEvap = double.NaN; } else { readMetData.PanEvap = Convert.ToSingle(values[this.evaporationIndex], CultureInfo.InvariantCulture); } if (this.rainfallHoursIndex == -1) { readMetData.RainfallHours = double.NaN; } else { readMetData.RainfallHours = Convert.ToSingle(values[this.rainfallHoursIndex], CultureInfo.InvariantCulture); } if (this.vapourPressureIndex == -1) { readMetData.VP = Math.Max(0, MetUtilities.svp(readMetData.MinT)); } else { readMetData.VP = Convert.ToSingle(values[this.vapourPressureIndex], CultureInfo.InvariantCulture); } if (this.windIndex == -1) { readMetData.Wind = 3.0; } else { readMetData.Wind = Convert.ToSingle(values[this.windIndex], CultureInfo.InvariantCulture); } if (this.DiffuseFractionIndex == -1) { // Estimate Diffuse Fraction using the Approach of Bristow and Campbell double Qmax = MetUtilities.QMax(clock.Today.DayOfYear + 1, Latitude, MetUtilities.Taz, MetUtilities.Alpha, 0.0); // Radiation for clear and dry sky (ie low humidity) double Q0 = MetUtilities.Q0(clock.Today.DayOfYear + 1, Latitude); double B = Qmax / Q0; double Tt = MathUtilities.Bound(readMetData.Radn / Q0, 0, 1); if (Tt > B) { Tt = B; } readMetData.DiffuseFraction = (1 - Math.Exp(0.6 * (1 - B / Tt) / (B - 0.4))); if (Tt > 0.5 && readMetData.DiffuseFraction < 0.1) { readMetData.DiffuseFraction = 0.1; } } else { readMetData.DiffuseFraction = Convert.ToSingle(values[this.DiffuseFractionIndex], CultureInfo.InvariantCulture); } if (this.dayLengthIndex == -1) // Daylength is not a column - check for a constant { if (this.reader.Constant("daylength") != null) { readMetData.DayLength = this.reader.ConstantAsDouble("daylength"); } else { readMetData.DayLength = -1; } } else { readMetData.DayLength = Convert.ToSingle(values[this.dayLengthIndex], CultureInfo.InvariantCulture); } return(readMetData); }
private void OnDoWeather(object sender, EventArgs e) { if (this.doSeek) { if (!this.OpenDataFile()) { throw new ApsimXException(this, "Cannot find weather file '" + this.FileName + "'"); } this.doSeek = false; this.reader.SeekToDate(this.clock.Today); } object[] values; try { values = this.reader.GetNextLineOfData(); } catch (IndexOutOfRangeException err) { throw new Exception($"Unable to retrieve weather data on {clock.Today.ToString("yyy-MM-dd")} in file {FileName}", err); } if (this.clock.Today != this.reader.GetDateFromValues(values)) { throw new Exception("Non consecutive dates found in file: " + this.FileName + ". Another posibility is that you have two clock objects in your simulation, there should only be one"); } if (this.radiationIndex != -1) { this.Radn = Convert.ToSingle(values[this.radiationIndex], CultureInfo.InvariantCulture); } else { this.Radn = this.reader.ConstantAsDouble("radn"); } if (this.maximumTemperatureIndex != -1) { this.MaxT = Convert.ToSingle(values[this.maximumTemperatureIndex], CultureInfo.InvariantCulture); } else { this.MaxT = this.reader.ConstantAsDouble("maxt"); } if (this.minimumTemperatureIndex != -1) { this.MinT = Convert.ToSingle(values[this.minimumTemperatureIndex], CultureInfo.InvariantCulture); } else { this.MinT = this.reader.ConstantAsDouble("mint"); } if (this.rainIndex != -1) { this.Rain = Convert.ToSingle(values[this.rainIndex], CultureInfo.InvariantCulture); } else { this.Rain = this.reader.ConstantAsDouble("rain"); } if (this.evaporationIndex == -1) { this.PanEvap = double.NaN; } else { this.PanEvap = Convert.ToSingle(values[this.evaporationIndex], CultureInfo.InvariantCulture); } if (this.rainfallHoursIndex == -1) { this.RainfallHours = double.NaN; } else { this.RainfallHours = Convert.ToSingle(values[this.rainfallHoursIndex], CultureInfo.InvariantCulture); } if (this.vapourPressureIndex == -1) { this.VP = Math.Max(0, MetUtilities.svp(this.MinT)); } else { this.VP = Convert.ToSingle(values[this.vapourPressureIndex], CultureInfo.InvariantCulture); } if (this.windIndex == -1) { this.Wind = 3.0; } else { this.Wind = Convert.ToSingle(values[this.windIndex], CultureInfo.InvariantCulture); } if (this.DiffuseFractionIndex == -1) { this.DiffuseFraction = -1; } else { this.DiffuseFraction = Convert.ToSingle(values[this.DiffuseFractionIndex], CultureInfo.InvariantCulture); } if (this.dayLengthIndex == -1) // Daylength is not a column - check for a constant { if (this.reader.Constant("daylength") != null) { this.DayLength = this.reader.ConstantAsDouble("daylength"); } else { this.DayLength = -1; } } else { this.DayLength = Convert.ToSingle(values[this.dayLengthIndex], CultureInfo.InvariantCulture); } if (this.PreparingNewWeatherData != null) { this.PreparingNewWeatherData.Invoke(this, new EventArgs()); } if (First) { //StartDAWS = met.DaysSinceWinterSolstice; if (clock.Today.DayOfYear < WinterSolsticeDOY) { if (DateTime.IsLeapYear(clock.Today.Year)) { DaysSinceWinterSolstice = 366 - WinterSolsticeDOY + clock.Today.DayOfYear - 1; //minus 1 as we set the first day as zero } else { DaysSinceWinterSolstice = 365 - WinterSolsticeDOY + clock.Today.DayOfYear - 1; } } else { DaysSinceWinterSolstice = clock.Today.DayOfYear - WinterSolsticeDOY; } First = false; } if (clock.Today.DayOfYear == WinterSolsticeDOY & First == false) { DaysSinceWinterSolstice = 0; } else { DaysSinceWinterSolstice += 1; } Qmax = MetUtilities.QMax(clock.Today.DayOfYear + 1, Latitude, MetUtilities.Taz, MetUtilities.Alpha, VP); }