Skip to content
Snippets Groups Projects
Commit bf7cdccb authored by Lene Wasskog's avatar Lene Wasskog
Browse files

Merge branch 'main' into release

parents 46027f67 545ad51f
No related branches found
No related tags found
No related merge requests found
Pipeline #3646 passed
......@@ -10,7 +10,7 @@
<groupId>no.nibio.vips.model</groupId>
<artifactId>DayDegreesModel</artifactId>
<version>0.1.0</version>
<version>0.1.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
......
/*
* Copyright (c) 2016 NIBIO <http://www.nibio.no/>.
*
* This file is part of PsilaRosaeTempModel.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package no.nibio.vips.model.daydegreemodel;
import no.nibio.vips.util.DateMap;
/**
* @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
public class DataMatrix extends DateMap{
public final static String TMD = "TMD";
public final static String TMD0C = "TMD0C";
}
/*
* Copyright (c) 2016 NIBIO <http://www.nibio.no/>.
*
* This file is part of PsilaRosaeTempModel.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package no.nibio.vips.model.daydegreemodel;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.Result;
import no.nibio.vips.entity.ResultImpl;
import no.nibio.vips.entity.WeatherObservation;
import no.nibio.vips.i18n.I18nImpl;
import no.nibio.vips.model.ConfigValidationException;
import no.nibio.vips.model.Model;
import no.nibio.vips.model.ModelExcecutionException;
import no.nibio.vips.model.ModelId;
import no.nibio.vips.util.ModelUtil;
import no.nibio.vips.util.CommonNamespaces;
import no.nibio.vips.util.InvalidAggregationTypeException;
import no.nibio.vips.util.WeatherElements;
import no.nibio.vips.util.WeatherObservationListException;
import no.nibio.vips.util.WeatherUtil;
/**
* @copyright 2016-2021 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor J. Johansen <tor.johansen@nibio.no> (Model research)
* @author Tor-Einar Skog <tor-einar.skog@nibio.no> (Programming)
*/
public class DayDegreeModel extends I18nImpl implements Model {
public final static ModelId MODEL_ID = new ModelId("DAYDEGREES");
private final ModelUtil modelUtil;
private TimeZone timeZone;
private DataMatrix dataMatrix;
private List<WeatherObservation> TM; // Temporary storage of hourly values
private final Double dayDegreeBaseTemp = 0.0;
// Threshold values
//private final Double THRESHOLD_1 = 260.0;
//private final Double THRESHOLD_2 = 360.0;
//private final Double THRESHOLD_3 = 560.0;
public DayDegreeModel()
{
super("no.nibio.vips.model.psilarosaetempmodel.texts");
this.modelUtil = new ModelUtil();
}
@Override
public List<Result> getResult() throws ModelExcecutionException {
this.calculateTemperatureSum(DataMatrix.TMD, DataMatrix.TMD0C);
List<Result> retVal = new ArrayList<>();
Date currentDate = this.dataMatrix.getFirstDateWithParameterValue(DataMatrix.TMD0C);
Calendar cal = Calendar.getInstance(this.timeZone);
DecimalFormat dFormat = new DecimalFormat("###.##");
while(this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.TMD0C) != null)
{
Result result = new ResultImpl();
result.setValidTimeStart(currentDate);
Double TMCurrentDate = ((WeatherObservation) this.dataMatrix.getParamValueForDate(currentDate, DataMatrix.TMD)).getValue();
Double TMD0C = this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.TMD0C);
/*
result.setValue(CommonNamespaces.NS_WEATHER, DataMatrix.TMD, dFormat.format(TMCurrentDate));
result.setValue(CommonNamespaces.NS_WEATHER, DataMatrix.TMDD5C, dFormat.format(TMDD5C));
result.setValue(CommonNamespaces.NS_WEATHER, DataMatrix.TMD5C, dFormat.format(TMD5C));
result.setValue(PsilaRosaeTempModel.MODEL_ID.toString(), "THRESHOLD_1", dFormat.format(this.THRESHOLD_1));
result.setValue(PsilaRosaeTempModel.MODEL_ID.toString(), "THRESHOLD_2", dFormat.format(this.THRESHOLD_2));
result.setValue(PsilaRosaeTempModel.MODEL_ID.toString(), "THRESHOLD_3", dFormat.format(this.THRESHOLD_3));
Integer warningStatus = Result.WARNING_STATUS_NO_RISK;
if(TMDD5C >= this.THRESHOLD_1)
{
warningStatus = Result.WARNING_STATUS_MINOR_RISK;
}
if(TMDD5C >= this.THRESHOLD_2)
{
warningStatus = Result.WARNING_STATUS_HIGH_RISK;
}
if(TMDD5C >= this.THRESHOLD_3)
{
warningStatus = Result.WARNING_STATUS_NO_WARNING;
}
result.setWarningStatus(warningStatus);
retVal.add(result);
// Moving on...
cal.setTime(currentDate);
cal.add(Calendar.DATE, 1);
currentDate = cal.getTime();*/
}
return null;
//return retVal;
}
@Override
public ModelId getModelId() {
return DayDegreeModel.MODEL_ID;
}
@Override
public String getModelName() {
return this.getModelName(Model.DEFAULT_LANGUAGE);
}
@Override
public String getModelName(String language) {
return this.getText("name", language);
}
@Override
public String getLicense() {
return "/*\n" +
" * Copyright (c) 2016 NIBIO <http://www.nibio.no/>. \n" +
" * \n" +
" * This file is part of PsilaRosaeTempModel.\n" +
" * This program is free software: you can redistribute it and/or modify\n" +
" * it under the terms of the GNU Affero General Public License as published by\n" +
" * the Free Software Foundation, either version 3 of the License, or\n" +
" * (at your option) any later version.\n" +
" *\n" +
" * This program is distributed in the hope that it will be useful,\n" +
" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
" * GNU Affero General Public License for more details.\n" +
" *\n" +
" * You should have received a copy of the GNU Affero General Public License\n" +
" * along with this program. If not, see <https://www.gnu.org/licenses/>.\n" +
" */";
}
@Override
public String getCopyright() {
return "(c) 2015-2021 NIBIO (http://www.nibio.no/). Contact: post@nibio.no";
}
@Override
public String getModelDescription() {
return this.getModelDescription(Model.DEFAULT_LANGUAGE);
}
@Override
public String getModelDescription(String language) {
try
{
return this.modelUtil.getTextWithBase64EncodedImages(this.getText("description", language), this.getClass());
}
catch(IOException ex)
{
return this.getText("description", language);
}
}
@Override
public String getWarningStatusInterpretation() {
return this.getWarningStatusInterpretation(Model.DEFAULT_LANGUAGE);
}
@Override
public String getWarningStatusInterpretation(String language) {
return this.getText("statusInterpretation", language);
}
@Override
public String getModelUsage() {
return this.getModelUsage(Model.DEFAULT_LANGUAGE);
}
@Override
public String getModelUsage(String language) {
return this.getText("usage", language);
}
@Override
public String getSampleConfig() {
return "{\n" +
"\t\"loginInfo\":{\n" +
"\t\t\"username\":\"example\",\n" +
"\t\t\"password\":\"example\"\n" +
"\t},\n" +
"\t\"modelId\":\"" + MODEL_ID.toString() + "\",\n" +
"\t\"configParameters\":{\n" +
"\t\t\"timeZone\": \"Europe/Oslo\",\n" +
"\t\t\"observations\":[\n" +
"\t\t{\n" +
"\t\t\t\t\"timeMeasured\": \"2015-01-01T00:00:00+02:00\",\n" +
"\t\t\t\t\"elementMeasurementTypeId\":\"TM\",\n" +
"\t\t\t\t\"logIntervalId\":2,\n" +
"\t\t\t\t\"value\":-1.1\n" +
"\t\t}\n" +
"}\n";
}
@Override
public void setConfiguration(ModelConfiguration config) throws ConfigValidationException {
// Initialize the weather data collections
this.TM = new ArrayList<>();
// Init data matrix
this.dataMatrix = new DataMatrix();
// Setting timezone
this.timeZone = TimeZone.getTimeZone((String) config.getConfigParameter("timeZone"));
//System.out.println("TimeZone=" + this.timeZone);
// Importing weather data, creating collections
// Can accept both hourly and daily data
WeatherUtil wUtil = new WeatherUtil();
List<WeatherObservation> observations = modelUtil.extractWeatherObservationList(config.getConfigParameter("observations"));
if(observations == null || observations.isEmpty())
{
throw new ConfigValidationException("Please provide weather data.");
}
for(WeatherObservation o:observations)
{
switch(o.getElementMeasurementTypeId())
{
case WeatherElements.TEMPERATURE_MEAN:
if(o.getLogIntervalId().equals(WeatherObservation.LOG_INTERVAL_ID_1H))
{
this.TM.add(o);
}else {
o.setTimeMeasured(wUtil.pragmaticAdjustmentToMidnight(o.getTimeMeasured(), timeZone));
this.dataMatrix.setParamValueForDate(o.getTimeMeasured(), DataMatrix.TMD, o);
}break;
default:
// Keep calm and continue importing data
break;
}
}
// If we've received hourly weather data, create and store daily values
// Air temperature
if(dataMatrix.getFirstDateWithParameterValue(DataMatrix.TMD) == null)
{
try {
List<WeatherObservation> dailyTemperatures = new WeatherUtil().getAggregatedDailyValues(
this.TM,
this.timeZone,
15,
WeatherUtil.AGGREGATION_TYPE_AVERAGE,
0,
true);
for(WeatherObservation obs:dailyTemperatures)
{
this.dataMatrix.setParamValueForDate(obs.getTimeMeasured(), DataMatrix.TMD, obs);
}
} catch (WeatherObservationListException | InvalidAggregationTypeException ex) {
throw new ConfigValidationException(ex.getMessage());
}
}
//System.out.println("DataMatrix");
//System.out.println(this.dataMatrix.toString());
}
/**
* Operates on the datamatrix
* @param inputParameterName the parameter to sum
* @param outputParameterName the result
*/
private void calculateTemperatureSum(String inputParameterName, String outputParameterName) throws ModelExcecutionException {
Date today = this.dataMatrix.getFirstDateWithParameterValue(inputParameterName);
Date lastDate = this.dataMatrix.getLastDateWithParameterValue(inputParameterName);
Calendar cal = Calendar.getInstance(this.timeZone);
Double sum = 0.0;
while(today.compareTo(lastDate) <= 0)
{
WeatherObservation todayTemp = (WeatherObservation)this.dataMatrix.getParamValueForDate(today, inputParameterName);
if(todayTemp == null)
{
throw new ModelExcecutionException("Missing weather data at " + today + ": " + inputParameterName);
}
//System.out.println("today=" + today + ",todayTemp=" + todayTemp);
Double dailyContribution = Math.max(0.0, todayTemp.getValue() - this.dayDegreeBaseTemp);
this.dataMatrix.setParamDoubleValueForDate(today, DataMatrix.TMD0C, dailyContribution);
sum += dailyContribution;
this.dataMatrix.setParamDoubleValueForDate(today, outputParameterName, sum);
cal.setTime(today);
cal.add(Calendar.DATE, 1);
today = cal.getTime();
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment