From 1e91d73164f0710e56dbf598b2b1ca57ffdf45fc Mon Sep 17 00:00:00 2001
From: jtn <jtn@omoikane>
Date: Tue, 23 Apr 2019 16:44:55 +0300
Subject: [PATCH] Added tracking for days since the start of the model

The tracking starts from the first day of the weather data, and tracks
if enough days have passed. If enough days have passed, the effect of
tillage will be changed from Tillage to TillageEffectAfter parameter in
the configuration file. TillageEffectDays sets the number of days for
this to happen.

If the effect is not wanted in a model run, it can be disabled by
setting the timeTillageEffects parameter to false. By default, the
effect is in use.
---
 resources/model-constants.json                |  6 ++
 .../model/cerealmodels/FinnCerealModels.java  | 11 +++
 .../mtt/model/diseasepressure/BaseRisk.java   | 39 ++++++++++-
 .../diseasepressure/DiseasePressureModel.java | 67 ++++++++++++++++++-
 .../cerealmodels/FinnCerealModelsTest.java    |  1 +
 5 files changed, 120 insertions(+), 4 deletions(-)

diff --git a/resources/model-constants.json b/resources/model-constants.json
index 7e6f89a..0360133 100644
--- a/resources/model-constants.json
+++ b/resources/model-constants.json
@@ -9,6 +9,8 @@
       "Pulse":{ "Intensive":{ "Value":-30 }, "Reduced":{ "Value":-70 }, "None":{ "Value":-100 } }
     },
     "Tillage":{ "Intensive":{ "Value":100 }, "Reduced":{ "Value":150 }, "None":{ "Value":200 } },
+    "TillageEffectDays":{ "Value":30 }, 
+    "TillageEffectAfter" : { "Intensive":{ "Value":150 }, "Reduced":{ "Value":150 }, "None":{ "Value":200 } },
     "CropSusceptibility":{ "Sensitive":{ "Value":1.5 }, "Normal":{ "Value":1 }, "Resistant":{ "Value":0.5 } },
     "DiseaseProgress":{ "[0,9]":{ "Value":1 }, "[10,19]":{ "Value":1 }, "[20,29]":{ "Value":1 }, "[30,44]":{ "Value":1.1 }, "[45,[":{ "Value":1.2 } },
     "SporeDevelopment":{
@@ -42,6 +44,8 @@
       "Pulse":{ "Intensive":{ "Value":-30 }, "Reduced":{ "Value":-70 }, "None":{ "Value":-100 } }
     },
     "Tillage":{ "Intensive":{ "Value":100 }, "Reduced":{ "Value":150 }, "None":{ "Value":200 } },
+    "TillageEffectDays":{ "Value":30 }, 
+    "TillageEffectAfter" : { "Intensive":{ "Value":150 }, "Reduced":{ "Value":150 }, "None":{ "Value":200 } },
     "CropSusceptibility":{ "Sensitive":{ "Value":1.5 }, "Normal":{ "Value":1 }, "Resistant":{ "Value":0.5 } },
     "DiseaseProgress":{ "[0,9]":{ "Value":1 }, "[10,19]":{ "Value":1 }, "[20,29]":{ "Value":1 }, "[30,44]":{ "Value":1 }, "[45,[":{ "Value":1.2 } },
     "SporeDevelopment":{
@@ -76,6 +80,8 @@
       "Pulse":{ "Intensive":{ "Value":-50 }, "Reduced":{ "Value":-100 }, "None":{ "Value":-100 } }
     },
     "Tillage":{ "Intensive":{ "Value":100 }, "Reduced":{ "Value":150 }, "None":{ "Value":200 } },
+    "TillageEffectDays":{ "Value":30 }, 
+    "TillageEffectAfter" : { "Intensive":{ "Value":150 }, "Reduced":{ "Value":150 }, "None":{ "Value":200 } },
     "CropSusceptibility":{ "Sensitive":{ "Value":1.5 }, "Normal":{ "Value":1 }, "Resistant":{ "Value":0.5 } },
     "DiseaseProgress":{ "[0,9]":{ "Value":1 }, "[10,19]":{ "Value":1 }, "[20,29]":{ "Value":1 }, "[30,44]":{ "Value":1.1 }, "[45,[":{ "Value":1.2 } },
     "SporeDevelopment":{
diff --git a/src/main/java/fi/luke/vips/model/cerealmodels/FinnCerealModels.java b/src/main/java/fi/luke/vips/model/cerealmodels/FinnCerealModels.java
index 65f5f34..5dbd816 100644
--- a/src/main/java/fi/luke/vips/model/cerealmodels/FinnCerealModels.java
+++ b/src/main/java/fi/luke/vips/model/cerealmodels/FinnCerealModels.java
@@ -117,8 +117,13 @@ public class FinnCerealModels implements Model {
 		List<Result> resultList = new ArrayList<>();
 		// reset model
 		Double accumulatedRisk = 0.0;
+		// sowing date now presumed to be the first date in the data set
+		// XXX this may be a bad idea
+		Date firstDate = dailyTemperature2.get(0).getTimeMeasured();
+		m.setSowingDay(firstDate);
 		for(int i=0; i < dailyTemperature2.size(); i++) {
 			Date currentDate = dailyTemperature2.get(i).getTimeMeasured();
+			m.setCurrentDay(currentDate);
 			Result r = new ResultImpl();
 			m.setTemperature(dailyTemperature2.get(i).getValue());
 			r.setValue(pathogen, "ATemp", ""+dailyTemperature2.get(i).getValue());
@@ -325,6 +330,12 @@ public class FinnCerealModels implements Model {
 			} else {
 				m.setDailyLeafWetnessDuration(d);
 			}
+			Boolean b = (Boolean)arg0.getConfigParameter("timeTillageEffects");
+			if(b == null) {
+				m.setTimeTillageEffects(true);
+			} else {
+				m.setTimeTillageEffects(b);
+			}
 
 			// weather information
                         ObjectMapper objectMapper = new ObjectMapper();
diff --git a/src/main/java/fi/uef/envi/mtt/model/diseasepressure/BaseRisk.java b/src/main/java/fi/uef/envi/mtt/model/diseasepressure/BaseRisk.java
index 3349680..24206cd 100644
--- a/src/main/java/fi/uef/envi/mtt/model/diseasepressure/BaseRisk.java
+++ b/src/main/java/fi/uef/envi/mtt/model/diseasepressure/BaseRisk.java
@@ -7,6 +7,7 @@ package fi.uef.envi.mtt.model.diseasepressure;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Calendar;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
@@ -37,6 +38,7 @@ public class BaseRisk implements Risk {
 	private String tillageType;
 	private String cropSusceptibilityType;
 	private String pathogenType;
+	private boolean tillageEffect;
 	private static ObjectMapper mapper = new ObjectMapper();
 
 	public BaseRisk() throws JsonProcessingException, IOException {
@@ -52,8 +54,13 @@ public class BaseRisk implements Risk {
 			throw new NullPointerException("[node = null]");
 
 		this.node = node;
+		this.tillageEffect = true;
 	}
 
+	public void setTillageEffect(boolean b) {
+		tillageEffect=b;
+	}
+	
 	public void setPathogen(String type) {
 		this.pathogenType = type;
 	}
@@ -65,7 +72,7 @@ public class BaseRisk implements Risk {
 	public void setTillage(String type) {
 		this.tillageType = type;
 	}
-
+	
 	public void setCropSusceptibility(String type) {
 		this.cropSusceptibilityType = type;
 	}
@@ -120,7 +127,11 @@ public class BaseRisk implements Risk {
 
 		double a = n.asDouble();
 
-		n = pathogenTypeNode.get("Tillage");
+		if(tillageEffect) {
+			n = pathogenTypeNode.get("Tillage");
+		} else {
+			n = pathogenTypeNode.get("TillageEffectAfter");
+		}
 
 		if (n == null)
 			throw new NullPointerException("Tillage not found [pathogenType = "
@@ -168,4 +179,28 @@ public class BaseRisk implements Risk {
 
 		return (a + b) * c;
 	}
+
+	public boolean isTillageInEffect(Calendar sowingDay, Calendar currentDay) {
+		// TODO Auto-generated method stub
+		JsonNode pathogenTypeNode = node.get(pathogenType);
+		JsonNode n = pathogenTypeNode.get("TillageEffectDays");
+		if (n == null)
+			throw new NullPointerException(
+					"Value not found [pathogenType = "
+							+ pathogenType + "; TillageEffectDays ]");
+
+		n = n.get("Value");
+		if (n == null)
+			throw new NullPointerException(
+					"Value not found [pathogenType = "
+							+ pathogenType + "; TillageEffectDays ]");
+		int days = n.asInt();
+		// less days since sowing than the maximum that the tillage is in effect
+		return (currentDay.get(Calendar.DAY_OF_YEAR) < (sowingDay.get(Calendar.DAY_OF_YEAR)+days));
+	}
+
+	public boolean getTillageEffect() {
+		// TODO Auto-generated method stub
+		return tillageEffect;
+	}
 }
diff --git a/src/main/java/fi/uef/envi/mtt/model/diseasepressure/DiseasePressureModel.java b/src/main/java/fi/uef/envi/mtt/model/diseasepressure/DiseasePressureModel.java
index 8342d9f..f4f6c45 100644
--- a/src/main/java/fi/uef/envi/mtt/model/diseasepressure/DiseasePressureModel.java
+++ b/src/main/java/fi/uef/envi/mtt/model/diseasepressure/DiseasePressureModel.java
@@ -10,6 +10,8 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.List;
 
 import com.fasterxml.jackson.databind.JsonNode;
@@ -42,17 +44,37 @@ public class DiseasePressureModel {
 	private SporeSpreading sporeSpreading;
 	private InfectionProbability infectionProbability;
 	private ObjectMapper mapper = new ObjectMapper();
+	private Calendar sowingDay, currentDay;
+	// if timeTillageEffects is true, then the model keeps track of how long it has been
+	// since tillage, and at certain point stops using the Tillage configuration value
+	// and starts using the TillageEffectAfter -value. 
+	// if timeTillageEffects is false, the value of Tillage field in the configuration is used
+	// always. The default is true if sowing date is given, false otherwise
+	private boolean timeTillageEffects;
 
 	public DiseasePressureModel() {
 		this(DiseasePressureModel.class.getClassLoader().getResourceAsStream(
-				Options.MODEL_CONSTANTS_FILE));
+				Options.MODEL_CONSTANTS_FILE), new Date());
 	}
 
+	public DiseasePressureModel(Date date) {
+		this(DiseasePressureModel.class.getClassLoader().getResourceAsStream(
+				Options.MODEL_CONSTANTS_FILE), date);
+	}
+
+	public DiseasePressureModel(File file, Date date) throws FileNotFoundException {
+		this(new FileInputStream(file), date);
+	}
+	
 	public DiseasePressureModel(File file) throws FileNotFoundException {
-		this(new FileInputStream(file));
+		this(new FileInputStream(file), new Date());
 	}
 
 	public DiseasePressureModel(InputStream stream) {
+		this(stream, new Date());
+	}
+	
+	public DiseasePressureModel(InputStream stream, Date sowingDay) {
 		JsonNode node;
 
 		try {
@@ -61,6 +83,18 @@ public class DiseasePressureModel {
 			throw new RuntimeException(e);
 		}
 
+		this.sowingDay = Calendar.getInstance();
+		this.currentDay = Calendar.getInstance();
+		timeTillageEffects = false;
+		if(sowingDay != null) {
+			this.sowingDay.setTime(sowingDay);
+			this.currentDay.setTime(sowingDay);
+			timeTillageEffects = true;
+		}
+//		this.sowingDay.set(Calendar.HOUR_OF_DAY,0);
+//		this.sowingDay.set(Calendar.MINUTE,0);
+//		this.sowingDay.set(Calendar.SECOND,0);
+//		this.sowingDay.set(Calendar.MILLISECOND,1);
 		baseRisk = new BaseRisk(node);
 		dailyRisk = new DailyRisk();
 		accumulatedRisk = new AccumulatedRisk(node);
@@ -125,8 +159,29 @@ public class DiseasePressureModel {
 	public void setLeafIsWet(List<Boolean> leafIsWet) {
 		sporeSpreading.setLeafIsWet(leafIsWet);
 	}
+		
+	public void setSowingDay(Date d) {
+		sowingDay.setTime(d);
+	}
 
+	public void setCurrentDay(Date d) {
+//		if(currentDay == null) {
+//			currentDay = Calendar.getInstance();
+//		}
+		currentDay.setTime(d);
+//		currentDay.set(Calendar.HOUR_OF_DAY,0);
+//		currentDay.set(Calendar.HOUR,0);
+//		currentDay.set(Calendar.MINUTE,0);
+//		currentDay.set(Calendar.MILLISECOND,1);
+	}
+	
 	public double getBaseRisk() {
+		// tillage is not timed, thus it is always on.
+		if(!timeTillageEffects) {
+			baseRisk.setTillageEffect(true);
+		} else if(baseRisk.getTillageEffect()) {
+			baseRisk.setTillageEffect(baseRisk.isTillageInEffect(sowingDay,currentDay));
+		}
 		return baseRisk.compute();
 	}
 
@@ -137,6 +192,14 @@ public class DiseasePressureModel {
 	public double getAccumulatedRisk() {
 		return accumulatedRisk.compute();
 	}
+
+	public boolean isTimeTillageEffects() {
+		return timeTillageEffects;
+	}
+
+	public void setTimeTillageEffects(boolean timeTillageEffects) {
+		this.timeTillageEffects = timeTillageEffects;
+	}
         
       
 
diff --git a/src/test/java/fi/luke/vips/model/cerealmodels/FinnCerealModelsTest.java b/src/test/java/fi/luke/vips/model/cerealmodels/FinnCerealModelsTest.java
index 5155020..61cbf01 100644
--- a/src/test/java/fi/luke/vips/model/cerealmodels/FinnCerealModelsTest.java
+++ b/src/test/java/fi/luke/vips/model/cerealmodels/FinnCerealModelsTest.java
@@ -136,6 +136,7 @@ public class FinnCerealModelsTest {
         m.setConfigParameter("rh", rh);
         m.setConfigParameter("windspeed", windSpeedAll);
 
+        m.setConfigParameter("timeTillageEffects", new Boolean(false));
 		m.setConfigParameter("precedingCrop","Wheat");
 		m.setConfigParameter("tillageMethod","Intensive");
 		m.setConfigParameter("diseaseSusceptibility","Normal");
-- 
GitLab