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

first commit

parents
No related branches found
No related tags found
No related merge requests found
target/
classes/
pom.xml 0 → 100644
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>no.bioforsk.vips.model.</groupId>
<artifactId>NaerstadModel</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>NaerstadModel</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>no.bioforsk.vips.common</groupId>
<artifactId>VIPSCommon</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.6.3</version>
<type>jar</type>
</dependency>
</dependencies>
</project>
package no.bioforsk.vips.model.naerstadmodel;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import no.bioforsk.no.vips.i18n.I18nImpl;
import no.bioforsk.vips.entity.ModelConfiguration;
import no.bioforsk.vips.entity.Observation;
import no.bioforsk.vips.entity.Result;
import no.bioforsk.vips.entity.ResultImpl;
import no.bioforsk.vips.model.Model;
import no.bioforsk.vips.model.ModelId;
import no.bioforsk.vips.util.WeatherElements;
import no.bioforsk.vips.util.WeatherUtil;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
/**
* Implementation of the Nærstad model for Potato Blight<br/>
* Developed by <a href="http://www.bioforsk.no/ikbViewer/page/bioforsk/ansatte/person?p_document_id=7146&p_dimension_id=17661">Ragnhild Nærstad</a>
* @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
* @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
*/
public class NaerstadModel extends I18nImpl implements Model{
private boolean DEBUG = true;
private Collection<Observation> TM;
private Collection<Observation> UM;
private Collection<Observation> RR;
//private Collection<KlimaTimeverdiBO> FM2;
private Collection<Observation> Q0;
private Collection<Observation> BT;
private Date calculationStart;
private Date calculationEnd;
private NaerstadModelBackgroundDataMatrix backgroundData;
private WeatherUtil weatherUtil;
private final static ModelId MODEL_ID = new ModelId("NAERSTADMO");
public NaerstadModel(){
// Setting the file name of the resource bundle
super("no.bioforsk.vips.model.naerstadmodel.texts");
}
@Override
public List<Result> getResult() {
this.calculateNaerstadModellBakgroundData();
this.backgroundData.toString();
List<Result> results = new ArrayList<>();
Calendar cal = Calendar.getInstance();
cal.setTime(this.calculationStart);
/*
* Results can only be inferred from 1 day after calculation start.
* Therefore we add one day before we begin iteration
*/
cal.add(Calendar.DATE, 1);
DecimalFormat dFormat = new DecimalFormat("###.##");
for(int j=0;j<4;j++)
{
Date dateStart = cal.getTime();
cal.add(Calendar.DATE, 1);
Date dateEnd = cal.getTime();
Date thePresent = dateStart;
while(thePresent.before(dateEnd))
{
Result result = new ResultImpl();
result.setResultValidTime(thePresent);
Double RISK = this.backgroundData.getParamDoubleValueForDate(thePresent, NaerstadModelBackgroundDataMatrix.RISK);
// TODO: Find better way of terminating?
if(RISK == null)
{
break;
}
if(this.DEBUG)
System.out.println("RISK(" + thePresent + ")=" + RISK);
result.setValue("RISK", dFormat.format(RISK));
results.add(result);
// Moving on
cal.setTime(thePresent);
cal.add(Calendar.HOUR_OF_DAY, 1);
thePresent = cal.getTime();
}
}
return results;
}
public ModelId getModelId() {
return NaerstadModel.MODEL_ID;
}
public String getModelName() {
return this.getModelName(Model.DEFAULT_LANGUAGE);
}
public String getModelName(String language) {
return this.getText("name", language);
}
public String getModelUsage() {
return this.getModelUsage(Model.DEFAULT_LANGUAGE);
}
public String getModelUsage(String language) {
return this.getText("usage", language);
}
/**
* TODO: Input control!!!!!
* @param config
*/
@Override
public void setConfiguration(ModelConfiguration config) {
initCollections();
ObjectMapper mapper = new ObjectMapper();
this.calculationStart = mapper.convertValue(config.getConfigParameter("calculationStart"), new TypeReference<Date>(){});
this.calculationEnd = mapper.convertValue(config.getConfigParameter("calculationEnd"), new TypeReference<Date>(){});
List<Observation> observations = mapper.convertValue(config.getConfigParameter("observations"), new TypeReference<List<Observation>>(){});
for(Observation o:observations)
{
switch(o.getElementMeasurementTypeId())
{
case WeatherElements.TEMPERATURE_MEAN:
this.TM.add(o); break;
case WeatherElements.PRECIPITATION:
this.RR.add(o); break;
case WeatherElements.LEAF_WETNESS:
this.BT.add(o); break;
case WeatherElements.GLOBAL_RADIATION:
this.Q0.add(o); break;
case WeatherElements.RELATIVE_HUMIDITY:
this.UM.add(o); break;
default:
// TODO: Throw validation error?
break;
}
}
// TODO: Validate all input!!!!
/*for(Observation o:observations)
{
System.out.println("o time Measured = " + o.getTimeMeasured());
}
catch(ArrayIndexOutOfBoundsException aioue)
{
throw new Exception("Feil med antall måledata. TMliste.length = " + TMliste.length + ", BTliste.length=" + BTliste.length + ", UMListe.length=" + UMliste.length + ", RRliste.length=" + RRliste.length + ", Q0liste.length=" + Q0liste.length);
}*/
}
/**
* Sets up the collections
*/
private void initCollections(){
this.BT = new ArrayList();
this.Q0 = new ArrayList();
this.RR = new ArrayList();
this.TM = new ArrayList();
this.UM = new ArrayList();
}
/**
* Calculates all background data for the model
* Depends on continuous weather data. This should be validated beforehand.
*/
private void calculateNaerstadModellBakgroundData()
{
this.backgroundData = new NaerstadModelBackgroundDataMatrix();
Collections.sort((List)this.TM);
Collections.sort((List)this.UM);
Collections.sort((List)this.RR);
Collections.sort((List)this.BT);
Collections.sort((List)this.Q0);
Observation[] TMliste = new Observation[0];
TMliste = this.TM.toArray(TMliste);
Observation[] UMliste = new Observation[0];
UMliste = this.UM.toArray(UMliste);
Observation[] RRliste = new Observation[0];
RRliste = this.RR.toArray(RRliste);
Observation[] BTliste = new Observation[0];
BTliste = this.BT.toArray(BTliste);
Observation[] Q0liste = new Observation[0];
Q0liste = this.Q0.toArray(Q0liste);
// For debugging purposes only!
Calendar cal = Calendar.getInstance();
cal.set(2012, 9, 11, 0, 0, 0);
Date debugLimitDate = cal.getTime();
boolean first = true;
for(Integer i=0;i<TMliste.length;i++)
{
// Calculating TSHH (Temperature Sum Humid Hours)
Double TSHHLastHour = first ? 0 : this.backgroundData.getParamDoubleValueForDate(TMliste[i-1].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.TSHH);
Double TSHH;
Integer HH1 = this.getHH1(TMliste[i].getValue(), UMliste[i].getValue());
if(first)
{
TSHH = 0d;
}
else if(HH1 == 1)
{
TSHH = this.getHH2(TMliste[i].getValue(), UMliste[i].getValue()) * (TSHHLastHour + (HH1 * TMliste[i].getValue()));
}
else
{
TSHH = this.getHH2(TMliste[i].getValue(), UMliste[i].getValue()) * 0.75 * TSHHLastHour;
}
this.backgroundData.setParamDoubleValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.TSHH, TSHH);
// Calculating SPH (Spore producing hour)
Integer SPH = TSHH >= 87 ? 1 : 0;
this.backgroundData.setParamIntValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.SPH, SPH);
// Calculating VAS (Viable Attached Spore)
Double VASLastHour = first ? 0 : this.backgroundData.getParamDoubleValueForDate(TMliste[i-1].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.VAS);
Double WVD = this.getWeatherUtil().getWVD(TMliste[i].getValue(), UMliste[i].getValue());
this.backgroundData.setParamDoubleValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WVD, WVD);
Double VAS = ((VASLastHour * 0.95 * (1-((WVD-220)/6000))) + SPH) / (1 + (RRliste[i].getValue() * 0.3));
if(DEBUG)
{
//System.out.println(VAS + " = ((" + VASLastHour + " * 0.95 * (1-((" + WVD + "-220)/6000))) + " + SPH+ ") / (1 + (" + RRliste[i].getValue() + " * 0.3));");
}
this.backgroundData.setParamDoubleValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.VAS, VAS);
// Calculating VRS (Viable released spores)
Double VRS = 0d;
if(i > 0)
{
Double VRSLastHour = this.backgroundData.getParamDoubleValueForDate(TMliste[i-1].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.VRS);
Integer WHSLastHour = this.backgroundData.getParamIntValueForDate(TMliste[i-1].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WHS);
if(VRSLastHour != null && WHSLastHour != null)
{
// RTA (Release To Air)
Integer RTA = this.getRAD(Q0liste[i].getValue(),Q0liste[i-1].getValue()) + this.getDROP(WVD, this.backgroundData.getParamDoubleValueForDate(TMliste[i-1].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WVD));
// IRTA (Inhibition of Release To Air)
Double IRTA = 1-((double) BTliste[i].getValue() / 80);
// SFRS (Survival Factor of Released Spores)
Double SFRS = (1 - (Q0liste[i].getValue() - 270)/540)/1.5;
if(DEBUG)
{
//System.out.println(TMliste[i].getTimeMeasured().toString() + ": SPH=" + SPH + ", RR[t]=" + RRliste[i].getValue() + ", WVD=" + WVD + ", VAS=" + VAS + ", RTA=" + RTA + ", IRTA=" + IRTA + ", SFRS=" + SFRS + ", VRSLastHour=" + VRSLastHour + ", WHSLastHour=" + WHSLastHour);
}
VRS = this.getVRS(VAS, RTA, IRTA, SFRS, VRSLastHour, (double) RRliste[i].getValue(), WHSLastHour);
}
}
this.backgroundData.setParamDoubleValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.VRS, VRS);
if(i > 0 && i < TMliste.length-8)
{
// Need to calculate WH for this hour and four hours into the future. But only the first time
// From the second time on, we only need to calculate for the fourth hour into the future, as all the
// other values have already been calculated
for(int j = 0; j < 5 ; j++)
{
// WHS (Wetness starts)
Integer WHS = 0;
Double WVDLastHour = this.getWeatherUtil().getWVD(TMliste[i+j-1].getValue(), UMliste[i+j-1].getValue());
Double WVDThisHour = this.getWeatherUtil().getWVD(TMliste[i+j].getValue(), UMliste[i+j].getValue());
if( WVDLastHour + WVDThisHour < 180
|| (i+j < TMliste.length -1 && RRliste[i+j].getValue() > 0.1)
|| (i+j < TMliste.length -3 && BTliste[i+j].getValue() + BTliste[i+j+1].getValue() + BTliste[i+j+2].getValue() > 122)
|| (i+j < TMliste.length -1 && BTliste[i+j].getValue() > 42)
)
{
WHS = 1;
}
else
{
WHS = 0;
}
if(DEBUG && WHS == 1)
{
//Double BTSum = BTliste[i+j].getValue() + BTliste[i+j+1].getValue() + BTliste[i+j+2].getValue();
}
// Lagrer denne
this.backgroundData.setParamIntValueForDate(TMliste[i+j].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WHS, WHS);
// Wetness continuation (WHC)
Integer WHC = 0;
if(WVDThisHour < 340 || RRliste[i+j].getValue() > 0.1)
{
WHC = 1;
}
// Wetness Duration (WD)
Double WDLastHour = 0d;
if(i > 1)
{
WDLastHour = this.backgroundData.getParamDoubleValueForDate(TMliste[i+j-1].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WD);
}
Double WD = WHC * (WDLastHour + WHS);
this.backgroundData.setParamDoubleValueForDate(TMliste[i+j].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WD, WD);
// Wet Hours (WH)
Integer WH = WD > 0 ? 1 : 0;
this.backgroundData.setParamIntValueForDate(TMliste[i+j].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WH, WH);
}
// Calculating TSWH
Double TSWH;
Integer WHS = this.backgroundData.getParamIntValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WHS);
if(WHS == 0)
{
TSWH = 0d;
}
else
{
//Collecting data
Integer[] WH = new Integer[5];
for(int k=0;k<WH.length;k++)
{
WH[k] = this.backgroundData.getParamIntValueForDate(TMliste[i+k].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WH);
}
TSWH = (WH[0] * ((double)TMliste[i].getValue() + WH[1] * ((double)TMliste[i+1].getValue() + WH[2]*((double)TMliste[i+2].getValue() + WH[3] * ((double)TMliste[i+3].getValue() + WH[4] * ((double)TMliste[i+4].getValue()))))));
}
this.backgroundData.setParamDoubleValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.TSWH, TSWH);
// Calculating IR (Infection risk)
Integer IR = TSWH >= 40 ? 1 : 0;
this.backgroundData.setParamIntValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.IR, IR);
// Calculating RISK.
Double RISK = IR ==1 ? (TSWH/40) * VRS : 0d;
this.backgroundData.setParamDoubleValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.RISK, RISK);
}
if(first) first = false;
if(TMliste[i].getTimeMeasured().after(debugLimitDate))
{
this.DEBUG = false;
}
if(this.DEBUG)
{
System.out.println("[NaerstadsModellActivityBean] DEBUG Dagens dato = " + TMliste[i].getTimeMeasured().toString() + ", " +
"TSWH=" + this.backgroundData.getParamDoubleValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.TSWH) + ", " +
"WH=" + this.backgroundData.getParamIntValueForDate(TMliste[i].getTimeMeasured(), NaerstadModelBackgroundDataMatrix.WH) + ", " +
"TM=" + TMliste[i].getValue());
}
}
}
protected Double getTSWH(Integer WHt0, Integer WHt1, Integer WHt2, Integer WHt3, Integer WHt4, Double Tt0, Double Tt1, Double Tt2, Double Tt3, Double Tt4)
{
return (WHt0 * (Tt0 + WHt1 * (Tt1 + WHt2 * (Tt2 + WHt3 *(Tt3 + WHt4 * (Tt4))))));
}
/**
* Calculating the VSR value
* @param VAS
* @param RTA
* @param IRTA
* @param SFRS
* @param VRSLastHour
* @param RR
* @param WHSLastHour
* @return
*/
protected Double getVRS(Double VAS, Integer RTA, Double IRTA, Double SFRS, Double VRSLastHour, Double RR, Integer WHSLastHour)
{
return (((VAS*RTA*IRTA*SFRS) + (VRSLastHour * 0.95 * SFRS)) / (1 + (RR * 0.1))) / (1 + (WHSLastHour * VRSLastHour * 0.1));
}
/**
*
* @param currentRadiation
* @param previousRadiation
* @return
*/
protected Integer getRAD(double currentRadiation, double previousRadiation)
{
return currentRadiation - previousRadiation > 7 ? 1 : 0;
}
protected Integer getDROP(double currentWVD, double previousWVD)
{
return currentWVD - previousWVD >= 15 ? 1 : 0;
}
/**
*
* @param date
* @param parameterName
* @return
*/
protected Double getCalculatedParameter(Date date, String parameterName)
{
if(this.backgroundData == null)
{
this.calculateNaerstadModellBakgroundData();
}
return this.backgroundData.getParamDoubleValueForDate(date, parameterName);
}
protected Integer getHH1(double temperature, double relativeHumidity)
{
return this.getWeatherUtil().getWVD(temperature, relativeHumidity) <= 220 ? 1 : 0;
}
protected Integer getHH2(double temperature, double relativeHumidity)
{
return this.getWeatherUtil().getWVD(temperature, relativeHumidity) <= 520 ? 1 : 0;
}
private WeatherUtil getWeatherUtil()
{
if(this.weatherUtil == null)
{
this.weatherUtil = new WeatherUtil();
}
return this.weatherUtil;
}
}
package no.bioforsk.vips.model.naerstadmodel;
/**
* Matrix with calculated background data for Naerstad Model
* &copy; 2009 Bioforsk.no
* @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
*/
public class NaerstadModelBackgroundDataMatrix extends no.bioforsk.vips.util.DateMap{
public final static String TSHH = "TSHH";
public final static String SPH = "SPH";
public final static String VAS = "VAS";
public final static String WVD = "WVD";
public final static String VRS = "VRS";
public final static String TSWH = "TSWH";
public final static String WD = "WD";
public final static String WHS = "WHS";
public final static String WH = "WH";
public final static String IR = "IR";
public final static String RISK = "RISK";
public NaerstadModelBackgroundDataMatrix()
{
super();
}
}
# To change this template, choose Tools | Templates
# and open the template in the editor.
name=Naerstad Model
usage=To be announced
# To change this template, choose Tools | Templates
# and open the template in the editor.
name=N\u00e6rstads modell
usage=Spesifiseres senere
package no.bioforsk.vips.model.naerstadmodel;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment