From ff849cec742b759d79cb91643fd51bfa0f7ba8c9 Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@nibio.no>
Date: Tue, 28 May 2024 14:38:27 +0200
Subject: [PATCH] Make sure RISK never is displayed as negative

---
 .../model/naerstadmodel/NaerstadModel.java    | 51 +++++++++----
 .../naerstadmodel/NaerstadModelTest.java      | 73 +++++++++++++++++--
 2 files changed, 104 insertions(+), 20 deletions(-)

diff --git a/src/main/java/no/nibio/vips/model/naerstadmodel/NaerstadModel.java b/src/main/java/no/nibio/vips/model/naerstadmodel/NaerstadModel.java
index d48928c..f372def 100755
--- a/src/main/java/no/nibio/vips/model/naerstadmodel/NaerstadModel.java
+++ b/src/main/java/no/nibio/vips/model/naerstadmodel/NaerstadModel.java
@@ -28,8 +28,10 @@ import java.util.Calendar;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import no.nibio.vips.i18n.I18nImpl;
 import no.nibio.vips.entity.ModelConfiguration;
 import no.nibio.vips.entity.WeatherObservation;
@@ -51,7 +53,7 @@ import no.nibio.vips.util.WeatherUtil;
  * @author Tor-Einar Skog <tor-einar.skog@nibio.no>
  */
 public class NaerstadModel extends I18nImpl implements Model{
-    
+    private static Logger LOGGER = LoggerFactory.getLogger(NaerstadModel.class);
     private boolean DEBUG = false;
     
     private List<WeatherObservation> TM;
@@ -97,7 +99,10 @@ public class NaerstadModel extends I18nImpl implements Model{
              */
             cal.add(Calendar.DATE, 1);
             DecimalFormat dFormat = new DecimalFormat("###.##");
-            //System.out.println("RESULTS: " + this.backgroundData.toString());
+            if(DEBUG)
+            {
+                System.out.println("RESULTS: " + this.backgroundData.toString());
+            }
             Date thePresent = cal.getTime();
             while(thePresent.compareTo(calculationEnd) <= 0)
             {
@@ -110,6 +115,10 @@ public class NaerstadModel extends I18nImpl implements Model{
                 {
                     break;
                 }
+
+                // The risk value should never be displayed as negative
+                RISK = Math.max(0.0, RISK);
+
                 if(this.DEBUG)
                     System.out.println("RISK(" + thePresent + ")=" + RISK);
                 
@@ -147,7 +156,7 @@ public class NaerstadModel extends I18nImpl implements Model{
             if(e instanceof ModelExcecutionException)
                 throw e;
             // Log the error
-            Logger.getLogger(NaerstadModel.class.getName()).log(Level.SEVERE, null, e);
+            LOGGER.error(e.getMessage(), e);
             throw new ModelExcecutionException("An exception occurred. Message is " + e.getMessage() + " See logs for details");
         }
     }
@@ -338,13 +347,23 @@ public class NaerstadModel extends I18nImpl implements Model{
      * 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();
+        this.BT = new ArrayList<>();
+        this.Q0 = new ArrayList<>();
+        this.RR = new ArrayList<>();
+        this.TM = new ArrayList<>();
+        this.UM = new ArrayList<>();
     }
     
+    /**
+     * Survival factor of released spores
+     * @param Q0 Solar radiation value (Hourly w/sqm)
+     * @return
+     */
+    public Double getSFRS(Double Q0)
+    {
+        return (1 - (Q0 - 270)/540)/1.5;
+    }
+
     /**
      * Calculates all background data for the model
      * Depends on continuous weather data. This should be validated beforehand.
@@ -419,7 +438,7 @@ public class NaerstadModel extends I18nImpl implements Model{
             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));");
+                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);
 
@@ -437,14 +456,16 @@ public class NaerstadModel extends I18nImpl implements Model{
                     // 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;
+                    Double SFRS = this.getSFRS(Q0liste[i].getValue());
+
+                    
+
+                    VRS = this.getVRS(VAS, RTA, IRTA, SFRS, VRSLastHour, (double) RRliste[i].getValue(), WHSLastHour);
 
                     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);
+                        System.out.println(TMliste[i].getTimeMeasured().toString() + ": SPH=" + SPH + ", RR[t]=" + RRliste[i].getValue() + ", WVD=" + WVD + ", VAS=" + VAS + ", RTA=" + RTA + ", IRTA=" + IRTA + ", VRS = " + VRS + ", 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);
diff --git a/src/test/java/no/nibio/vips/model/naerstadmodel/NaerstadModelTest.java b/src/test/java/no/nibio/vips/model/naerstadmodel/NaerstadModelTest.java
index 43d9e15..e866ba8 100755
--- a/src/test/java/no/nibio/vips/model/naerstadmodel/NaerstadModelTest.java
+++ b/src/test/java/no/nibio/vips/model/naerstadmodel/NaerstadModelTest.java
@@ -110,10 +110,11 @@ public class NaerstadModelTest extends TestCase {
      * Test of getResult method, of class NaerstadModel.
      */
     public void testGetResult() {
+        
         try {
             System.out.println("getResult");
             NaerstadModel instance = new NaerstadModel();
-            ModelConfiguration config = this.getConfiguration();
+            ModelConfiguration config = this.getConfiguration("/JSONWeatherData.json");
             instance.setConfiguration(config);
             //System.out.println(config.toJSON());
             List<Result> results;
@@ -135,9 +136,40 @@ public class NaerstadModelTest extends TestCase {
             }*/
             assertTrue(results.size() == 209);
         } catch (ConfigValidationException | ModelExcecutionException ex) {
-                fail("Exception: " + ex.getMessage());
+                fail("Exception: " + ex.getMessage());        
         }
+    }
+
+    public void testGetResultSwedishData()
+    {
+        try{
+            System.out.println("getResultSwedishData");
+            NaerstadModel instance = new NaerstadModel();
+            ModelConfiguration config = this.getConfiguration("/SLU_Faltforsk_GlyttingeGRID_2024.json");
+            instance.setConfiguration(config);
+            //System.out.println(config.toJSON());
+            List<Result> results;
+            results = instance.getResult();
+            /*for(int i=500;i<550;i++)
+            {
+                System.out.println(results.get(i));
+            }*/
+            //results.forEach(r->System.out.println(r));
+            //System.out.println("Result size=" + results.size());
+            
+            // Check for results list length
+            assertTrue(results.size() == 659);
+            // Check risk value for a result
+            Result r = results.get(549);
+            assertEquals(3.66, Double.parseDouble(r.getValue(instance.getModelId().toString(), NaerstadModelBackgroundDataMatrix.RISK)));
+            // Check risk value that would have been negative unless capped
+            r = results.get(results.size()-5);
+            assertEquals(0.0, Double.parseDouble(r.getValue(instance.getModelId().toString(), NaerstadModelBackgroundDataMatrix.RISK)));
 
+        }
+        catch (ConfigValidationException | ModelExcecutionException ex) {
+            fail("Exception: " + ex.getMessage());
+    }
     }
 
     /**
@@ -219,19 +251,19 @@ public class NaerstadModelTest extends TestCase {
             System.out.println("setConfiguration");
             
             NaerstadModel instance = new NaerstadModel();
-            instance.setConfiguration(this.getConfiguration());
+            instance.setConfiguration(this.getConfiguration("/JSONWeatherData.json"));
         } catch (ConfigValidationException ex) {
             fail("Error in configuration:" + ex.getMessage());
         }
         
     }
     
-    private ModelConfiguration getConfiguration()
+    private ModelConfiguration getConfiguration(String fileName)
     {
         try {
             ModelConfiguration config = new ModelConfiguration();
             config.setModelId("NAERSTADMO");
-            BufferedInputStream inputStream = new BufferedInputStream(this.getClass().getResourceAsStream("/JSONWeatherData.json"));
+            BufferedInputStream inputStream = new BufferedInputStream(this.getClass().getResourceAsStream(fileName));
             JsonFactory f = new MappingJsonFactory();
             JsonParser jp = f.createParser(inputStream);
             JsonNode all = jp.readValueAsTree();
@@ -366,7 +398,38 @@ public class NaerstadModelTest extends TestCase {
         NaerstadModel instance = new NaerstadModel();
         Double expResult = 3.0818301132374937;
         Double result = instance.getVRS(VAS, RTA, IRTA, SFRS, VRSLastHour, RR, WHSLastHour);
+
         assertEquals(expResult, result);
+
+        VAS = 1.8620744816150898;
+        RTA = 2;
+        IRTA = 1.0;
+        SFRS = -0.033086419753086314;
+        VRSLastHour = 3.625814763513186;
+        RR = 0.0;
+        WHSLastHour = 0;
+
+        result = instance.getVRS(VAS, RTA, IRTA, SFRS, VRSLastHour, RR, WHSLastHour);
+
+        assertEquals(-0.23718572357236287, result);
+
+    }
+
+    public void testGetSFRS() {
+        System.out.println("getSFRS");
+        Double Q0 = 0.0;
+        NaerstadModel instance = new NaerstadModel();
+        Double SFRS = instance.getSFRS(Q0);
+        Double expected = 1.0;
+
+        assertEquals(expected, SFRS);
+
+        Q0=836.8;
+        SFRS = instance.getSFRS(Q0);
+        expected = -0.033086419753086314;
+
+        assertEquals(expected, SFRS);
+
     }
 
     /**
-- 
GitLab