Skip to content
Snippets Groups Projects
Commit 2cbe908c authored by Tor-Einar Skog's avatar Tor-Einar Skog
Browse files

Handle grid based forecast configuration in the backend

parent 0fb0167a
Branches
No related tags found
1 merge request!191Add map module and Open-Meteo support
...@@ -127,7 +127,7 @@ public class ForecastConfiguration implements Serializable, Comparable { ...@@ -127,7 +127,7 @@ public class ForecastConfiguration implements Serializable, Comparable {
private Boolean useGridWeatherData; private Boolean useGridWeatherData;
public Boolean getUseGridWeatherData() { public Boolean getUseGridWeatherData() {
return useGridWeatherData; return useGridWeatherData != null ? this.useGridWeatherData:false;
} }
public void setUseGridWeatherData(Boolean useGridWeatherData) { public void setUseGridWeatherData(Boolean useGridWeatherData) {
...@@ -257,6 +257,29 @@ public class ForecastConfiguration implements Serializable, Comparable { ...@@ -257,6 +257,29 @@ public class ForecastConfiguration implements Serializable, Comparable {
* @return the weatherStationPointOfInterestId * @return the weatherStationPointOfInterestId
*/ */
public PointOfInterest getWeatherStationPointOfInterestId() { public PointOfInterest getWeatherStationPointOfInterestId() {
if( this.getUseGridWeatherData() && this.getVipsLogicUserId().getOrganizationId().getDefaultGridWeatherStationDataSource() != null)
{
// Create a "weather station" with coordinates from the location
// And the default grid weather data source for the current organization (get location owner's organization)
PointOfInterestWeatherStation gridStation = new PointOfInterestWeatherStation();
gridStation.setLatitude(this.getLocationPointOfInterestId().getLatitude());
gridStation.setLongitude(this.getLocationPointOfInterestId().getLongitude());
gridStation.setName("GRID-punkt for " + this.getLocationPointOfInterestId().getName()); // TODO Translate!!!
gridStation.setTimeZone(this.getLocationPointOfInterestId().getTimeZone());
gridStation.setWeatherStationDataSourceId(this.getVipsLogicUserId().getOrganizationId().getDefaultGridWeatherStationDataSource());
gridStation.setUser(this.getVipsLogicUserId());
gridStation.setWeatherForecastProviderId(null);
gridStation.setWeatherStationRemoteId(gridStation.getLongitude() + "_" + gridStation.getLatitude());
gridStation.setGisGeom(this.getLocationPointOfInterestId().getGisGeom());
gridStation.setAltitude(this.getLocationPointOfInterestId().getAltitude());
gridStation.setCountryCode(this.getLocationPointOfInterestId().getCountryCode());
gridStation.setIsForecastLocation(true);
gridStation.setPointOfInterestTypeId(PointOfInterestType.POINT_OF_INTEREST_TYPE_WEATHER_STATION);
gridStation.setUser(this.getVipsLogicUserId());
gridStation.setProperties(this.getLocationPointOfInterestId().getProperties());
return gridStation;
}
return weatherStationPointOfInterestId; return weatherStationPointOfInterestId;
} }
......
...@@ -111,6 +111,21 @@ public class Organization implements Serializable { ...@@ -111,6 +111,21 @@ public class Organization implements Serializable {
@OneToOne @OneToOne
@JsonIgnore @JsonIgnore
private VipsLogicUser archiveUser; private VipsLogicUser archiveUser;
@JoinColumn(name = "default_grid_weather_station_data_source_id", referencedColumnName = "weather_station_data_source_id")
@ManyToOne
private WeatherStationDataSource defaultGridWeatherStationDataSource;
public WeatherStationDataSource getDefaultGridWeatherStationDataSource() {
return defaultGridWeatherStationDataSource;
}
public void setDefaultGridWeatherStationDataSource(WeatherStationDataSource defaultGridWeatherStationDataSource) {
this.defaultGridWeatherStationDataSource = defaultGridWeatherStationDataSource;
}
public Organization() { public Organization() {
} }
......
...@@ -27,6 +27,10 @@ import java.util.Date; ...@@ -27,6 +27,10 @@ import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.TimeZone; import java.util.TimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import no.nibio.vips.entity.ModelConfiguration; import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.WeatherObservation; import no.nibio.vips.entity.WeatherObservation;
import no.nibio.vips.logic.entity.ForecastConfiguration; import no.nibio.vips.logic.entity.ForecastConfiguration;
...@@ -48,17 +52,13 @@ import no.nibio.vips.util.weather.WeatherDataSourceUtil; ...@@ -48,17 +52,13 @@ import no.nibio.vips.util.weather.WeatherDataSourceUtil;
* @author Tor-Einar Skog <tor-einar.skog@nibio.no> * @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/ */
public class AppleScabModelPreprocessor extends ModelRunPreprocessor{ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{
private static Logger LOGGER = LoggerFactory.getLogger(AppleScabModelPreprocessor.class);
private final boolean DEBUG = false;
public final static String APPLESCABM_START_DATE_ASCOSPORE_MATURITY = "APPLESCABM_START_DATE_ASCOSPORE_MATURITY"; public final static String APPLESCABM_START_DATE_ASCOSPORE_MATURITY = "APPLESCABM_START_DATE_ASCOSPORE_MATURITY";
@Override @Override
public ModelConfiguration getModelConfiguration(ForecastConfiguration configuration) throws PreprocessorException public ModelConfiguration getModelConfiguration(ForecastConfiguration configuration) throws PreprocessorException
{ {
if(DEBUG) LOGGER.debug("AppleScabModelPreprocessor.getModelConfiguration() called");
{
System.out.println("getModelConfiguration");
}
//configuration.getDateStart(); //configuration.getDateStart();
PointOfInterestWeatherStation weatherStation = (PointOfInterestWeatherStation) configuration.getWeatherStationPointOfInterestId(); PointOfInterestWeatherStation weatherStation = (PointOfInterestWeatherStation) configuration.getWeatherStationPointOfInterestId();
// What timezone is the calculation for // What timezone is the calculation for
...@@ -92,10 +92,8 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{ ...@@ -92,10 +92,8 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{
// Use Jackson to parse JSON from server // Use Jackson to parse JSON from server
// Weather data collections // Weather data collections
if(DEBUG) LOGGER.debug("Getting weather data at " + new Date().toString());
{
System.out.println("Getting weather data at " + new Date().toString());
}
WeatherDataSourceUtil wdsUtil = new WeatherDataSourceUtil(); WeatherDataSourceUtil wdsUtil = new WeatherDataSourceUtil();
List<WeatherObservation> observations; List<WeatherObservation> observations;
try { try {
...@@ -135,22 +133,17 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{ ...@@ -135,22 +133,17 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{
// We do nothing // We do nothing
} }
LOGGER.debug("Finished getting weather data at " + new Date().toString());
if(DEBUG)
{
System.out.println("Finished getting weather data at " + new Date().toString());
}
try { try {
observations = validateAndSanitizeObservations(observations, startDateAscosporeMaturity); observations = validateAndSanitizeObservations(observations, startDateAscosporeMaturity);
} catch (ConfigValidationException | WeatherObservationListException ex) { } catch (ConfigValidationException | WeatherObservationListException ex) {
//ex.printStackTrace(); //ex.printStackTrace();
throw new PreprocessorException(ex.getMessage()); throw new PreprocessorException(ex.getMessage());
} }
if(DEBUG)
{
System.out.println("Observations=" + observations.toString());
}
//LOGGER.debug("Observations=" + observations.toString());
// Create the complete model configuration object // Create the complete model configuration object
ModelConfiguration retVal = new ModelConfiguration(); ModelConfiguration retVal = new ModelConfiguration();
...@@ -176,11 +169,7 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{ ...@@ -176,11 +169,7 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{
* @throws WeatherObservationListException * @throws WeatherObservationListException
*/ */
private List<WeatherObservation> validateAndSanitizeObservations(List<WeatherObservation> observations, Date firstTimeStamp) throws ConfigValidationException, WeatherObservationListException { private List<WeatherObservation> validateAndSanitizeObservations(List<WeatherObservation> observations, Date firstTimeStamp) throws ConfigValidationException, WeatherObservationListException {
if(DEBUG)
{
System.out.println("validateAndSanitizeObservations");
}
WeatherUtil wUtil = new WeatherUtil(); WeatherUtil wUtil = new WeatherUtil();
// First we remove all duplicates // First we remove all duplicates
...@@ -241,14 +230,7 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{ ...@@ -241,14 +230,7 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{
// Problems with weather observations // Problems with weather observations
// Holes in series
if(DEBUG)
{
System.out.println("checkForAndFixHourlyTimeSeriesHoles");
//System.out.println(wUtil.dumpWeatherObservationList(RR));
}
// Unequal length of lists // Unequal length of lists
if ( if (
...@@ -257,6 +239,7 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{ ...@@ -257,6 +239,7 @@ public class AppleScabModelPreprocessor extends ModelRunPreprocessor{
|| RR.size() != TM.size() || RR.size() != TM.size()
) )
{ {
LOGGER.debug("Unequal lists lengt: RR=" + RR.size() + ", TM=" + TM.size() + ", BT=" + BT.size());
UM = wUtil.fixHourlyValuesForParameters( UM = wUtil.fixHourlyValuesForParameters(
UM, UM,
new HashSet(Arrays.asList("UM")), new HashSet(Arrays.asList("UM")),
......
...@@ -24,6 +24,10 @@ import java.util.Collections; ...@@ -24,6 +24,10 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.ejb.EJB; import javax.ejb.EJB;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import no.nibio.vips.i18n.I18nImpl; import no.nibio.vips.i18n.I18nImpl;
import no.nibio.vips.logic.controller.session.ForecastBean; import no.nibio.vips.logic.controller.session.ForecastBean;
import no.nibio.vips.logic.controller.session.PointOfInterestBean; import no.nibio.vips.logic.controller.session.PointOfInterestBean;
...@@ -46,6 +50,8 @@ import no.nibio.web.forms.FormField; ...@@ -46,6 +50,8 @@ import no.nibio.web.forms.FormField;
* @author Tor-Einar Skog <tor-einar.skog@nibio.no> * @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/ */
public class RunAllForecastConfigurationsTask extends VipsLogicTask{ public class RunAllForecastConfigurationsTask extends VipsLogicTask{
private static Logger LOGGER = LoggerFactory.getLogger(RunAllForecastConfigurationsTask.class);
private I18nImpl i18n; private I18nImpl i18n;
//private boolean DEBUG=true; //private boolean DEBUG=true;
...@@ -91,24 +97,30 @@ public class RunAllForecastConfigurationsTask extends VipsLogicTask{ ...@@ -91,24 +97,30 @@ public class RunAllForecastConfigurationsTask extends VipsLogicTask{
noForecastConfigurationsFound = false; noForecastConfigurationsFound = false;
for(ForecastConfiguration forecastConfiguration:currentForecastConfigurations) for(ForecastConfiguration forecastConfiguration:currentForecastConfigurations)
{ {
if( if(forecastConfiguration.getUseGridWeatherData() && forecastConfiguration.getWeatherStationPointOfInterestId() == null)
weatherStationPointOfInterestId == null {
|| weatherStationPointOfInterestId <= 0 errorMessage.append(
|| (forecastConfiguration.getWeatherStationPointOfInterestId() != null && forecastConfiguration.getWeatherStationPointOfInterestId().getPointOfInterestId().equals(weatherStationPointOfInterestId)) SchedulingUtil.createSchedulingMessageHTML(
"Error with forecast #" + forecastConfiguration.getForecastConfigurationId() + " (" + forecastConfiguration.getLocationPointOfInterestId().getName() + " - " + modelInformationMap.get(forecastConfiguration.getModelId()).getDefaultName() + ")",
"The forecast is configured to use gridded weather data, but the organization " + forecastConfiguration.getVipsLogicUserId().getOrganizationId().getOrganizationName() + " has not set its gridded weather data source. Please contact the system administrator.",
SchedulingUtil.MESSAGE_STATUS_WARNING
) )
);
totalNumberofForecastConfigurations++;
}
else if(
weatherStationPointOfInterestId == null
|| weatherStationPointOfInterestId <= 0
|| (forecastConfiguration.getWeatherStationPointOfInterestId() != null && forecastConfiguration.getWeatherStationPointOfInterestId().getPointOfInterestId().equals(weatherStationPointOfInterestId))
)
{ {
try try
{ {
totalNumberofForecastConfigurations++; totalNumberofForecastConfigurations++;
//System.out.println("Running forecast #" + forecastConfiguration.getForecastConfigurationId()); LOGGER.debug("Running forecast #" + forecastConfiguration.getForecastConfigurationId());
SessionControllerGetter.getForecastBean().runForecast(forecastConfiguration); SessionControllerGetter.getForecastBean().runForecast(forecastConfiguration);
/*
if(DEBUG && totalNumberofForecastConfigurations == 2)
{
throw new RunModelException("This is a test!!!");
}*/
numberOfCompletedForecastConfigurations++; numberOfCompletedForecastConfigurations++;
//System.out.println("All went well");
} }
catch (PreprocessorException | RunModelException ex) catch (PreprocessorException | RunModelException ex)
{ {
...@@ -119,38 +131,32 @@ public class RunAllForecastConfigurationsTask extends VipsLogicTask{ ...@@ -119,38 +131,32 @@ public class RunAllForecastConfigurationsTask extends VipsLogicTask{
ex.getMessage(), ex.getMessage(),
SchedulingUtil.MESSAGE_STATUS_DANGER) SchedulingUtil.MESSAGE_STATUS_DANGER)
); );
//System.out.println("########################### Error caught: " + errorMessage);
//System.out.println("numberOfCompletedForecastConfigurations=" + numberOfCompletedForecastConfigurations);
//System.out.println("totalNumberofForecastConfigurations=" + totalNumberofForecastConfigurations);
//continue;
} }
} }
if(totalNumberofForecastConfigurations > 0) if(totalNumberofForecastConfigurations > 0)
{ {
noForecastConfigurationsFound = false; noForecastConfigurationsFound = false;
double completeness = (double) numberOfCompletedForecastConfigurations/totalNumberofForecastConfigurations; tec.setCompleteness(Double.valueOf(numberOfCompletedForecastConfigurations)/Double.valueOf(totalNumberofForecastConfigurations));
tec.setCompleteness(completeness);
} }
else else
{ {
noForecastConfigurationsFound = true; noForecastConfigurationsFound = true;
//System.out.println("noForecastConfigurationsFound == true!!");
} }
//System.out.println("Current completeness=" + tec.getTaskExecutor().getCompleteness());
} }
} }
} }
if(noForecastConfigurationsFound) if(noForecastConfigurationsFound)
{ {
tec.setCompleteness(1.0); tec.setCompleteness(1.0);
tec.setStatusMessage("No current forecast configurations were found"); tec.setStatusMessage("No current forecast configurations were found");
} }
//System.out.println("Total completeness=" + tec.getTaskExecutor().getCompleteness());
if(tec.getTaskExecutor().getCompleteness() != 1.0) if(tec.getTaskExecutor().getCompleteness() != 1.0 || ! errorMessage.isEmpty())
{ {
//System.out.println("Error detected, RuntimeException thrown just after this"); //System.out.println("Error detected, RuntimeException thrown just after this");
tec.setStatusMessage(errorMessage.toString()); tec.setStatusMessage(errorMessage.toString());
......
-- Adding this property when adding support for gridded weather datasources in VIPS
ALTER TABLE organization
ADD COLUMN default_grid_weather_station_data_source_id INTEGER REFERENCES weather_station_data_source(weather_station_data_source_id) DEFAULT NULL;
\ No newline at end of file
...@@ -229,7 +229,7 @@ ...@@ -229,7 +229,7 @@
}; };
// Setting weather station select list state correct on page load // Setting weather station select list state correct on page load
handleUseGridWeatherDataClicked(document.getElementById("useGridWeatherData")<#if forecastConfiguration.weatherStationPointOfInterestId?has_content>,${forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId}</#if>); handleUseGridWeatherDataClicked(document.getElementById("useGridWeatherData")<#if forecastConfiguration.weatherStationPointOfInterestId?has_content && forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId?has_content>,${forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId}</#if>);
</script> </script>
</#macro> </#macro>
...@@ -328,7 +328,10 @@ ...@@ -328,7 +328,10 @@
<option value="-2">${i18nBundle.doNotUse} ${i18nBundle.weatherStationPointOfInterestId?lower_case}</option> <option value="-2">${i18nBundle.doNotUse} ${i18nBundle.weatherStationPointOfInterestId?lower_case}</option>
<option value="-1"<#if !forecastConfiguration.weatherStationPointOfInterestId?has_content && !forecastConfiguration.useGridWeatherData> selected="selected"</#if>>${i18nBundle.pleaseSelect} ${i18nBundle.weatherStationPointOfInterestId?lower_case}</option> <option value="-1"<#if !forecastConfiguration.weatherStationPointOfInterestId?has_content && !forecastConfiguration.useGridWeatherData> selected="selected"</#if>>${i18nBundle.pleaseSelect} ${i18nBundle.weatherStationPointOfInterestId?lower_case}</option>
<#list weatherStationPointOfInterests?sort_by("name") as poi> <#list weatherStationPointOfInterests?sort_by("name") as poi>
<option value="${poi.pointOfInterestId}"<#if forecastConfiguration.weatherStationPointOfInterestId?has_content && poi.pointOfInterestId == forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId> selected="selected"</#if>>${poi.name}</option> <option value="${poi.pointOfInterestId}"<#if
forecastConfiguration.weatherStationPointOfInterestId?has_content
&& forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId?has_content
&& poi.pointOfInterestId == forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId> selected="selected"</#if>>${poi.name}</option>
</#list> </#list>
</select> </select>
<span class="help-block" id="${formId}_weatherStationPointOfInterestId_validation"></span> <span class="help-block" id="${formId}_weatherStationPointOfInterestId_validation"></span>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment