From 59109433d90fec557e5d3048e5a72265a02a39e0 Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@nibio.no>
Date: Tue, 31 Jan 2023 14:44:21 +0100
Subject: [PATCH] Refactored reference_model out of this module

---
 src/vipscore_common/reference_model.py | 151 -------------------------
 tests/test_reference_model.py          |  96 ----------------
 2 files changed, 247 deletions(-)
 delete mode 100755 src/vipscore_common/reference_model.py
 delete mode 100644 tests/test_reference_model.py

diff --git a/src/vipscore_common/reference_model.py b/src/vipscore_common/reference_model.py
deleted file mode 100755
index 1fd3bf6..0000000
--- a/src/vipscore_common/reference_model.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/usr/bin/python3
-
-LICENSE = """
-Copyright (c) 2023 NIBIO <http://www.nibio.no/>. 
-
-This file is part of VIPSCore-Python-Common.
-VIPSCore-Python-Common 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.
- 
-VIPSCore-Python-Common 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 VIPSCore-Python-Common.  If not, see <http://www.nibio.no/licenses/>.
-"""
-
-from .vips_model import VIPSModel
-from .entities import Result, ModelConfiguration, WeatherObservation
-from .data_utils import *
-import numpy as np
-
-class ReferenceModel(VIPSModel):
-    """
-        A reference implementation of the VIPSModel abstract class. Showcasing core functionality
-        and best practices
-    """
-
-    MODEL_ID        = "REFERENCEM"
-    COPYRIGHT       = "(c) 2023 NIBIO"
-
-    THRESHOLD_LOW = 100.0
-    THRESHOLD_MEDIUM = 300.0
-    THRESHOLD_HIGH = 500.0
- 
-    def set_configuration(self, model_configuration: ModelConfiguration):
-        if not isinstance(model_configuration, ModelConfiguration):
-            raise ValueError("%s is not a ModelConfiguration object" % model_configuration)
-        if model_configuration.model_id != ReferenceModel.MODEL_ID:
-            raise ValueError("%s is not the correct model ID!" % model_configuration.model_id)
-        
-        # Input data check
-        self.sowing_date = model_configuration.get_config_parameter_as_date("sowingDate")
-        self.timezone = model_configuration.get_config_parameter_as_timezone("timeZone")
-        # Weather data is turned into Pandas dataframe
-        self.df = get_dataframe_from_weather_observations(
-                get_weather_observations_from_json_list(
-                    model_configuration.config_parameters["observations"]
-                    ),
-                self.timezone
-            )
-
-    
-
-    def determine_warning_status(self, TMDD: float) -> int:
-        """
-        Used in get_result as a dataframe operation. Determines the warning status
-        based on the model thresholds
-        """
-        if TMDD < ReferenceModel.THRESHOLD_MEDIUM:
-            return  Result.WARNING_STATUS_NO_WARNING
-        if TMDD < ReferenceModel.THRESHOLD_HIGH:
-            return Result.WARNING_STATUS_MINOR_RISK
-        else:
-            return Result.WARNING_STATUS_HIGH_RISK
-
-        
-    
-    def get_result(self) -> list[Result]:
-        """Get the results as a list of Result objects (TODO ref)"""
-        
-        # Calculate day degrees from sowingDate and as far as weather data goes
-        # Adjusting for base temperature
-        self.df["TMContrib"] = self.df["TM"].apply(get_temp_adjusted_for_base, args=(5,))
-        # Aggregating the day degrees
-        self.df["TMDD"] = self.df["TMContrib"].cumsum()
-        # Adding the thresholds to the data frame
-        self.df["THRESHOLD_LOW"] = ReferenceModel.THRESHOLD_LOW
-        self.df["THRESHOLD_MEDIUM"] = ReferenceModel.THRESHOLD_MEDIUM
-        self.df["THRESHOLD_HIGH"] = ReferenceModel.THRESHOLD_HIGH
-        # For each day: check accumulated day-degrees and decide warning status
-        self.df["WARNING_STATUS"] = self.df["TMDD"].apply(self.determine_warning_status)
-        #print(self.df)
-        result = get_result_list_from_dataframe(self.df)
-        #print(result)
-        return result
-        
-
-    @property
-    def model_id(self) -> str:
-        """10-character ID of the model. Must be unique (at least in the current system)"""
-        return ReferenceModel.MODEL_ID
-
-    
-    @property
-    def license(self) -> str:
-        """Returns the license for this piece of software"""
-        return LICENSE
-
-    @property
-    def copyright(self) -> str:
-        """Name of person/organization that holds the copyright, and contact information"""
-        return ReferenceModel.COPYRIGHT
-    
-    @property
-    def sample_config(self) -> dict:
-        """A sample configuration in JSON format (TODO check relation with Dict)"""
-        return """
-        {
-	model_id:'REFERENCEM',
-	config_parameters: {
-		'sowingDate': '2022-03-01', 
-		'observations': [
-			{'timeMeasured': '2015-03-01T00:00:00+01:00', 'elementMeasurementTypeId': 'TM', 'logIntervalId': '2', 'value': '1.41025'}, 
-			{'timeMeasured': '2015-03-02T00:00:00+01:00', 'elementMeasurementTypeId': 'TM', 'logIntervalId': '2', 'value': '2.87608333333333'}, 
-			{'timeMeasured': '2015-03-03T00:00:00+01:00', 'elementMeasurementTypeId': 'TM', 'logIntervalId': '2', 'value': '1.00854166666667'}, 
-			{'timeMeasured': '2015-03-04T00:00:00+01:00', 'elementMeasurementTypeId': 'TM', 'logIntervalId': '2', 'value': '-1.44675'}
-		]
-	}
-}
-        """
-
-    def get_model_name(self, language = VIPSModel.default_language) -> str:
-        """Returns the model name in the specified language (<a href="http://www.loc.gov/standards/iso639-2/php/English_list.php">ISO-639-2</a>)"""
-        return "Reference Model"     
-
-    def get_model_description(self, language = VIPSModel.default_language) -> str:
-        """Returns the model description in the specified language (<a href="http://www.loc.gov/standards/iso639-2/php/English_list.php">ISO-639-2</a>)"""
-        return """
-        The model is a reference model for developers, showcasing best practices and functionalities of a model.
-        It's a simple day degree model for an imagined pest, and when thresholds are passed, the warning status progresses.
-        """
-
-    def get_warning_status_interpretation(self, language = VIPSModel.default_language) -> str:
-        """How to interpret the warning status (red-yellow-green, what does it mean?) in the specified language (<a href="http://www.loc.gov/standards/iso639-2/php/English_list.php">ISO-639-2</a>)"""
-        return """
-        Gray   status (warning status == 0): Warning not applicable
-        Blue   status (warning status == 1): Missing data
-        Green  status (warning status == 2): No risk. Sleep well
-        Yellow status (warning status == 3): The day-degree hreshold for medium risk has been passed. Be on the alert, inspect your field
-        Red status    (warning status == 4): The day-degree threshold for high risk has been passed. When the going gets tough, the tough get going
-        """
-
-    def get_model_usage(self, language = VIPSModel.default_language) -> str:
-        """Technical manual for this model, in the specified language  (<a href="http://www.loc.gov/standards/iso639-2/php/English_list.php">ISO-639-2</a>)"""
-        return "TODO"
-
-    
\ No newline at end of file
diff --git a/tests/test_reference_model.py b/tests/test_reference_model.py
deleted file mode 100644
index 5d6ba90..0000000
--- a/tests/test_reference_model.py
+++ /dev/null
@@ -1,96 +0,0 @@
-import unittest
-
-import json
-
-from src.vipscore_common.reference_model import *
-from src.vipscore_common.entities import *
-
-def get_model_configuration():
-    with open ("tests/weather_data_2015_NO_aas_TMD.json") as f:
-        weather_observations = json.load(f)
-        return ModelConfiguration(
-            model_id=ReferenceModel.MODEL_ID,
-            config_parameters={
-                "sowingDate": "2022-03-01",
-                "timeZone" : "Europe/Oslo",
-                "observations": weather_observations
-            }
-        )
-
-class TestReferenceModel(unittest.TestCase):
-    def test_set_configuration(self):
-        """
-        Passing a configuration object does not fail
-        """
-        #print(get_model_configuration())
-        instance = ReferenceModel()
-        instance.set_configuration(get_model_configuration())
-
-    def test_get_result(self):
-        """
-        We get a series of results from the calculation,
-        and the TMDD is as expected
-        """
-        instance = ReferenceModel()
-        instance.set_configuration(get_model_configuration())
-        result_list = instance.get_result()
-        self.assertIsNotNone(result_list)
-        last_result = result_list[len(result_list)-1]
-        self.assertEqual(555.8507083333333, last_result.all_values["TMDD"])
-
-    def test_get_model_id(self):
-         """
-         The model returns the correct ID
-         """
-         instance = ReferenceModel()
-         self.assertEqual(instance.model_id, ReferenceModel.MODEL_ID)
-        
-    def test_get_license(self):
-        """
-        The model returns its license
-        """
-        instance = ReferenceModel()
-        self.assertIsNotNone(instance.license)
-
-    def test_get_copyright(self):
-        """
-        The model returns its copyright notice
-        """
-        instance = ReferenceModel()
-        self.assertEqual(instance.copyright, ReferenceModel.COPYRIGHT)
-    
-    def test_get_sample_config(self):
-        """
-        The model returns its sample configuration
-        """
-        instance = ReferenceModel()
-        self.assertIsNotNone(instance.sample_config)
-    
-    def test_get_model_name(self):
-        """
-        The model returns its name in the default language
-        """
-        instance = ReferenceModel()
-        self.assertEqual(instance.get_model_name(), "Reference Model")
-    
-    def test_get_model_description(self):
-        """
-        The model returns a description
-        """
-        instance = ReferenceModel()
-        self.assertIsNotNone(instance.get_model_description())
-    
-    def test_get_warning_status_interpretation(self):
-        """
-        The model returns a warning status interpretation
-        """
-        instance = ReferenceModel()
-        self.assertIsNotNone(instance.get_warning_status_interpretation())
-
-    def test_get_model_usage(self):
-        """
-        The model returns a description of usage
-        """
-
-if __name__ == '__main__':
-    unittest.main()
\ No newline at end of file
-- 
GitLab