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

Final adaptations to GIS aware result object

parent 5104f974
Branches
Tags
No related merge requests found
Showing
with 287 additions and 5 deletions
...@@ -96,6 +96,7 @@ public class ForecastResult implements Serializable, Comparable{ ...@@ -96,6 +96,7 @@ public class ForecastResult implements Serializable, Comparable{
this.allValues = new ObjectMapper().writeValueAsString(result.getAllValues()); this.allValues = new ObjectMapper().writeValueAsString(result.getAllValues());
this.validTimeStart = result.getValidTimeStart(); this.validTimeStart = result.getValidTimeStart();
this.warningStatus = result.getWarningStatus(); this.warningStatus = result.getWarningStatus();
this.validGeometry = result.getValidGeometry();
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(ForecastResult.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(ForecastResult.class.getName()).log(Level.SEVERE, null, ex);
} }
......
/*
* Copyright (c) 2018 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.scheduling.model.grid.preprocessor;
import com.vividsolutions.jts.geom.Coordinate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.PointWeatherObservationList;
import no.nibio.vips.entity.WeatherObservation;
import no.nibio.vips.logic.entity.ForecastConfiguration;
import no.nibio.vips.logic.entity.PointOfInterestWeatherStation;
import no.nibio.vips.logic.scheduling.model.ModelRunPreprocessor;
import no.nibio.vips.logic.scheduling.model.PreprocessorException;
import no.nibio.vips.logic.util.SessionControllerGetter;
import no.nibio.vips.util.WeatherElements;
import no.nibio.vips.util.WeatherObservationListException;
import no.nibio.vips.util.WeatherUtil;
import no.nibio.vips.util.weather.WeatherDataSourceException;
import no.nibio.vips.util.weather.WeatherDataSourceUtil;
/**
* @copyright 2018 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
public class ZymoseptoriaSimpleRiskGridModelPreprocessor extends ModelRunPreprocessor{
@Override
public ModelConfiguration getModelConfiguration(ForecastConfiguration configuration) throws PreprocessorException {
ModelConfiguration modelConfig = new ModelConfiguration();
// Which weather stations??
// Ilseng and Apelsvoll to start with ;-)
List<PointOfInterestWeatherStation> stations = Stream.of(new Integer[]{50,91}).map(
stationId -> (PointOfInterestWeatherStation) SessionControllerGetter.getPointOfInterestBean().getPointOfInterest(stationId)
).collect(Collectors.toList());
List<PointWeatherObservationList> allObs = new ArrayList<>();
for(PointOfInterestWeatherStation station:stations)
{
Coordinate coordinate = new Coordinate(station.getPointOfInterest().getLongitude(), station.getPointOfInterest().getLatitude());
List<WeatherObservation> stationObs = getStationObs(station, configuration);
PointWeatherObservationList pointObs = new PointWeatherObservationList(coordinate, stationObs);
allObs.add(pointObs);
}
modelConfig.setConfigParameter("multiPointWeatherObservations", allObs);
modelConfig.setModelId(this.getModelId());
modelConfig.setConfigParameter("timeZone", stations.get(0).getTimeZone());
return modelConfig;
}
@Override
public String getModelId() {
return "GRIDZYMOSE";
}
private List<WeatherObservation> getStationObs(PointOfInterestWeatherStation station, ForecastConfiguration configuration) throws PreprocessorException
{
List<WeatherObservation> stationObs;// = new ArrayList<>();
WeatherDataSourceUtil wdsUtil = new WeatherDataSourceUtil();
WeatherUtil wUtil = new WeatherUtil();
try {
stationObs = wdsUtil.getWeatherObservations(
station,
WeatherObservation.LOG_INTERVAL_ID_1H,
new String[]{
WeatherElements.LEAF_WETNESS,
WeatherElements.RELATIVE_HUMIDITY_MEAN,
WeatherElements.PRECIPITATION,
WeatherElements.TEMPERATURE_MEAN
},
configuration.getDateStartInTimeZone(),
configuration.getDateEndInTimeZone(),
true
);
stationObs = wUtil.checkForAndFixHourlyTimeSeriesHoles(stationObs);
return stationObs;
} catch (WeatherDataSourceException | WeatherObservationListException ex ) {
throw new PreprocessorException(ex.getMessage());
}
}
}
/*
* Copyright (c) 2018 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.scheduling.tasks;
import it.sauronsoftware.cron4j.TaskExecutionContext;
import java.util.Calendar;
import no.nibio.vips.logic.entity.ForecastConfiguration;
import no.nibio.vips.logic.entity.VipsLogicUser;
import no.nibio.vips.logic.scheduling.SchedulingUtil;
import no.nibio.vips.logic.scheduling.VipsLogicTask;
import no.nibio.vips.logic.scheduling.VipsLogicTaskFactory;
import no.nibio.vips.logic.scheduling.model.PreprocessorException;
import no.nibio.vips.logic.scheduling.model.grid.preprocessor.ZymoseptoriaSimpleRiskGridModelPreprocessor;
import no.nibio.vips.logic.util.RunModelException;
import no.nibio.vips.logic.util.SessionControllerGetter;
import no.nibio.vips.logic.util.SystemTime;
import no.nibio.web.forms.FormField;
/**
* @copyright 2018 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
public class RunGridModelsTask extends VipsLogicTask{
@Override
public String getConfigFormDefinition(String language) {
return "{\"fields\":[]}";
}
@Override
public void execute(TaskExecutionContext tec) throws RuntimeException {
tec.setCompleteness(0.0);
//ZymoseptoriaSimpleRiskGridModelPreprocessor pp = new ZymoseptoriaSimpleRiskGridModelPreprocessor();
// TODO: Must find a forecast configuration id! -1000 !
ForecastConfiguration fConfig = SessionControllerGetter.getForecastBean().getForecastConfiguration(-1000l);
try
{
SessionControllerGetter.getForecastBean().runForecast(fConfig);
tec.setCompleteness(1.0);
}
catch(PreprocessorException | RunModelException ex)
{
tec.setCompleteness(0.0);
tec.setStatusMessage(SchedulingUtil.createSchedulingMessageHTML(
"Error with forecast #" + fConfig.getForecastConfigurationId(),
ex.getMessage(),
SchedulingUtil.MESSAGE_STATUS_DANGER
)
);
ex.printStackTrace();
throw new RuntimeException();
}
}
@Override
public boolean supportsStatusTracking()
{
return true;
}
@Override
public boolean supportsCompletenessTracking()
{
return true;
}
}
...@@ -28,6 +28,7 @@ import java.util.ArrayList; ...@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import no.nibio.vips.gis.GISUtil;
import no.nibio.vips.logic.entity.Gis; import no.nibio.vips.logic.entity.Gis;
import no.nibio.vips.logic.entity.Observation; import no.nibio.vips.logic.entity.Observation;
import org.wololo.geojson.Feature; import org.wololo.geojson.Feature;
...@@ -79,7 +80,7 @@ public class GISEntityUtil { ...@@ -79,7 +80,7 @@ public class GISEntityUtil {
{ {
Gis gis = new Gis(); Gis gis = new Gis();
gis.setGisGeom(reader.read(feature.getGeometry())); gis.setGisGeom(reader.read(feature.getGeometry()));
gis.getGisGeom().setSRID(4326); gis.getGisGeom().setSRID(GISUtil.DEFAULT_SRID);
retVal.add(gis); retVal.add(gis);
} }
}catch(NullPointerException ex) {}; }catch(NullPointerException ex) {};
......
...@@ -59,11 +59,12 @@ public class WeatherDataSourceUtil { ...@@ -59,11 +59,12 @@ public class WeatherDataSourceUtil {
* @param elementMeasurementTypes Which parameters should be fetched * @param elementMeasurementTypes Which parameters should be fetched
* @param startTime When to start * @param startTime When to start
* @param endTime When to stop * @param endTime When to stop
* @param ignoreErrors if true, accepts errors and missing data from source
* @return * @return
* @throws PreprocessorException * @throws PreprocessorException
*/ */
public List<WeatherObservation> getWeatherObservations(PointOfInterestWeatherStation station, Integer logIntervalId, String[] elementMeasurementTypes, Date startTime, Date endTime) throws WeatherDataSourceException { public List<WeatherObservation> getWeatherObservations(PointOfInterestWeatherStation station, Integer logIntervalId, String[] elementMeasurementTypes, Date startTime, Date endTime, Boolean ignoreErrors) throws WeatherDataSourceException {
List<WeatherObservation> observations = this.getWeatherObservations(station.getDataFetchUri(), logIntervalId, elementMeasurementTypes, startTime, endTime, TimeZone.getTimeZone(station.getTimeZone())); List<WeatherObservation> observations = this.getWeatherObservations(station.getDataFetchUri(), logIntervalId, elementMeasurementTypes, startTime, endTime, TimeZone.getTimeZone(station.getTimeZone()), ignoreErrors);
Collections.sort(observations); Collections.sort(observations);
Date latestTimeOfMeasuredObservations = observations.isEmpty() ? null : observations.get(observations.size() - 1).getTimeMeasured(); Date latestTimeOfMeasuredObservations = observations.isEmpty() ? null : observations.get(observations.size() - 1).getTimeMeasured();
if (station.getWeatherForecastProviderId() != null) { if (station.getWeatherForecastProviderId() != null) {
...@@ -113,6 +114,30 @@ public class WeatherDataSourceUtil { ...@@ -113,6 +114,30 @@ public class WeatherDataSourceUtil {
return observations; return observations;
} }
/**
* Fetches measured data from the stations weather data source, and optionally
* a weather forecast provider (if so specified in the weather station configuration).
* Regarding weather forecast parameters: All requested parameters need be present in the
* forecast in order for any parameters to be fetched. So if you request e.g. TJM5 and TM,
* you won't get forecast values for any of them, because TJM5 is not present. Solve this
* by calling this method twice: Once for the parameters with forecasts, and one for the
* remaining.
*
* Requires the source to provide a complete data set (still, no guarantee)
*
* @param station The WeatherStation to fetch data from
* @param logIntervalId hourly/daily etc.
* @param elementMeasurementTypes Which parameters should be fetched
* @param startTime When to start
* @param endTime When to stop
* @return
* @throws PreprocessorException
*/
public List<WeatherObservation> getWeatherObservations(PointOfInterestWeatherStation station, Integer logIntervalId, String[] elementMeasurementTypes, Date startTime, Date endTime) throws WeatherDataSourceException
{
return this.getWeatherObservations(station, logIntervalId, elementMeasurementTypes, startTime, endTime, Boolean.FALSE);
}
public List<WeatherObservation> getWeatherObservations(String JSONtext) throws IOException { public List<WeatherObservation> getWeatherObservations(String JSONtext) throws IOException {
return new ObjectMapper().readValue(JSONtext, new TypeReference<List<WeatherObservation>>() { return new ObjectMapper().readValue(JSONtext, new TypeReference<List<WeatherObservation>>() {
}); });
...@@ -128,15 +153,26 @@ public class WeatherDataSourceUtil { ...@@ -128,15 +153,26 @@ public class WeatherDataSourceUtil {
* @param timeZone * @param timeZone
* @return * @return
*/ */
public List<WeatherObservation> getWeatherObservations(String fetchURI, Integer logIntervalId, String[] elementMeasurementTypes, Date startTime, Date endTime, TimeZone timeZone) throws WeatherDataSourceException { public List<WeatherObservation> getWeatherObservations(String fetchURI, Integer logIntervalId, String[] elementMeasurementTypes, Date startTime, Date endTime, TimeZone timeZone, Boolean ignoreErrors) throws WeatherDataSourceException {
SimpleDateFormat dateOutput = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat dateOutput = new SimpleDateFormat("yyyy-MM-dd");
dateOutput.setTimeZone(timeZone); dateOutput.setTimeZone(timeZone);
SimpleDateFormat hourOutput = new SimpleDateFormat("H"); SimpleDateFormat hourOutput = new SimpleDateFormat("H");
hourOutput.setTimeZone(timeZone); hourOutput.setTimeZone(timeZone);
StringBuilder URL = new StringBuilder(fetchURI).append(fetchURI.contains("?") ? "&" : "?").append("logIntervalId=").append(logIntervalId).append("&timeZone=").append(timeZone.getID()).append("&startDate=").append(dateOutput.format(startTime)).append("&startTime=").append(hourOutput.format(startTime)).append("&endDate=").append(dateOutput.format(endTime)).append("&endTime=").append(hourOutput.format(endTime)); StringBuilder URL = new StringBuilder(fetchURI)
.append(fetchURI.contains("?") ? "&" : "?")
.append("logIntervalId=").append(logIntervalId)
.append("&timeZone=").append(timeZone.getID())
.append("&startDate=").append(dateOutput.format(startTime))
.append("&startTime=").append(hourOutput.format(startTime))
.append("&endDate=").append(dateOutput.format(endTime))
.append("&endTime=").append(hourOutput.format(endTime));
for (String type : elementMeasurementTypes) { for (String type : elementMeasurementTypes) {
URL.append("&elementMeasurementTypes[]=").append(type); URL.append("&elementMeasurementTypes[]=").append(type);
} }
if(ignoreErrors)
{
URL.append("&ignoreErrors=true");
}
URLConnection URLConn = null; URLConnection URLConn = null;
InputStream URLStream = null; InputStream URLStream = null;
InputStream error = null; InputStream error = null;
......
/*
* Copyright (c) 2018 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
/**
* Author: Tor-Einar Skog <tor-einar.skog@nibio.no>
* Created: Feb 28, 2018
*/
-- Create POI type region as entity
CREATE TABLE public.point_of_interest_region (
point_of_interest_id INTEGER REFERENCES public.point_of_interest(point_of_interest_id) PRIMARY KEY REFERENCES public.point_of_interest(point_of_interest_id)
);
-- Create Region
INSERT INTO public.point_of_interest_type (point_of_interest_type_id, default_name) VALUES(4, 'Region');
-- Create the "Norden" region
WITH region AS(
INSERT INTO public.point_of_interest(name, point_of_interest_type_id, time_zone, user_id, gis_geom, is_forecast_location)
VALUES('Norden',4,'Europe/Oslo', (SELECT user_id FROM public.vips_logic_user WHERE first_name='Tor-Einar' and last_name='Skog'),
ST_GeomFromText('POLYGON Z ((11.551171875 67.9220301158979 0,14.7591796875 69.4854724192637 0,16.73671875 69.8064521798385 0,18.14296875 70.5952718386758 0,21.394921875 71.0142675856785 0,24.5150390625 71.5222863520185 0,28.426171875 71.438536696887 0,30.09609375 71.0713720920153 0,32.117578125 70.5952718386758 0,32.20546875 70.2120731914377 0,31.2826171875 69.8064521798384 0,31.062890625 69.4392213779 0,30.2279296875 69.3619145496807 0,29.656640625 69.1908599706792 0,29.04140625 68.7811487475743 0,28.865625 68.3637499431732 0,29.656640625 68.0866206437207 0,30.3158203125 67.6788323570344 0,29.480859375 66.9328949304538 0,30.44765625 65.8776814440396 0,30.4037109375 65.606865608295 0,30.0521484375 65.3698520724687 0,30.271875 65.1306805628583 0,29.9203125 64.9266077088153 0,30.6234375 64.8146360164186 0,30.359765625 64.4948403042286 0,30.887109375 64.2286381683626 0,30.44765625 63.7079270727349 0,31.6341796875 63.2170897962889 0,31.9857421875 62.6976281054899 0,27.371484375 60.0026032393766 0,26.844140625 59.9586321882202 0,28.3822265625 59.6713938591578 0,28.5140625 59.1120223258653 0,27.898828125 58.7719510110943 0,27.898828125 58.2439712430728 0,28.1625 57.7314817865778 0,28.6458984375 56.2961712709242 0,26.844140625 54.9817652590221 0,25.965234375 53.960342078609 0,23.5482421875 53.5446062737309 0,23.1966796875 54.0894167790577 0,22.36171875 54.3463659023544 0,22.4056640625 54.8048547300243 0,17.5716796875 56.1495794720281 0,14.8470703125 54.4742415202341 0,11.7708984375 54.3719729342547 0,7.46425781249998 55.0069747908166 0,7.37636718749998 57.4488421356283 0,5.61855468749998 57.8953424124117 0,4.21230468749998 59.1571122721993 0,3.77285156249998 61.776544291261 0,5.09121093749999 62.858445992293 0,9.39785156249999 64.8146360164187 0,11.3314453125 66.8984342861737 0,10.9359375 67.5617094491323 0,11.551171875 67.9220301158979 0))',4326), false)
RETURNING *
)
INSERT INTO public.point_of_interest_region(point_of_interest_id) SELECT region.point_of_interest_id FROM region;
...@@ -450,3 +450,6 @@ lastEditedBy=Last edited by ...@@ -450,3 +450,6 @@ lastEditedBy=Last edited by
clusterStored=The cluster information was stored clusterStored=The cluster information was stored
internal=Internal internal=Internal
vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter
pointOfInterestType_4=Region
task_RunGridModelsTask_name=Run grid models
task_RunGridModelsTask_description=Run models that cover several locations
...@@ -450,3 +450,6 @@ lastEditedBy=Last edited by ...@@ -450,3 +450,6 @@ lastEditedBy=Last edited by
clusterStored=The cluster information was stored clusterStored=The cluster information was stored
internal=Internal internal=Internal
vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter
pointOfInterestType_4=Region
task_RunGridModelsTask_name=Run grid models
task_RunGridModelsTask_description=Test
...@@ -449,3 +449,6 @@ lastEditedBy=Last edited by ...@@ -449,3 +449,6 @@ lastEditedBy=Last edited by
clusterStored=The cluster information was stored clusterStored=The cluster information was stored
internal=Internal internal=Internal
vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter
pointOfInterestType_4=Region
task_RunGridModelsTask_name=Run grid models
task_RunGridModelsTask_description=Test
...@@ -450,3 +450,6 @@ lastEditedBy=Sist redigert av ...@@ -450,3 +450,6 @@ lastEditedBy=Sist redigert av
clusterStored=Klasetallene ble registrert clusterStored=Klasetallene ble registrert
internal=Internt internal=Internt
vipsLogicRole_8=Rogneb\u00e6rm\u00f8llklaseteller vipsLogicRole_8=Rogneb\u00e6rm\u00f8llklaseteller
pointOfInterestType_4=Region
task_RunGridModelsTask_name=Kj\u00f8r GRID-baserte modeller
task_RunGridModelsTask_description=Kj\u00f8r modeller som spenner over flere lokaliteter
...@@ -450,3 +450,6 @@ lastEditedBy=Last edited by ...@@ -450,3 +450,6 @@ lastEditedBy=Last edited by
clusterStored=The cluster information was stored clusterStored=The cluster information was stored
internal=Internal internal=Internal
vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter
pointOfInterestType_4=Region
task_RunGridModelsTask_name=Run grid models
task_RunGridModelsTask_description=Test
...@@ -447,3 +447,6 @@ lastEditedBy=Last edited by ...@@ -447,3 +447,6 @@ lastEditedBy=Last edited by
clusterStored=The cluster information was stored clusterStored=The cluster information was stored
internal=Internal internal=Internal
vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter vipsLogicRole_8=Apple Fruit Moth Rowanberry Cluster Counter
pointOfInterestType_4=Region
task_RunGridModelsTask_name=Run grid models
task_RunGridModelsTask_description=Test
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment