views_pipeline_core 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. views_pipeline_core-0.1.0/LICENSE.md +21 -0
  2. views_pipeline_core-0.1.0/PKG-INFO +96 -0
  3. views_pipeline_core-0.1.0/README.md +76 -0
  4. views_pipeline_core-0.1.0/pyproject.toml +25 -0
  5. views_pipeline_core-0.1.0/views_pipeline_core/__init__.py +0 -0
  6. views_pipeline_core-0.1.0/views_pipeline_core/cache/__init__.py +0 -0
  7. views_pipeline_core-0.1.0/views_pipeline_core/cache/global_cache.py +237 -0
  8. views_pipeline_core-0.1.0/views_pipeline_core/cli/__init__.py +0 -0
  9. views_pipeline_core-0.1.0/views_pipeline_core/cli/utils.py +143 -0
  10. views_pipeline_core-0.1.0/views_pipeline_core/configs/drift_detection.py +35 -0
  11. views_pipeline_core-0.1.0/views_pipeline_core/configs/logging.yaml +62 -0
  12. views_pipeline_core-0.1.0/views_pipeline_core/data/__init__.py +0 -0
  13. views_pipeline_core-0.1.0/views_pipeline_core/data/dataloaders.py +304 -0
  14. views_pipeline_core-0.1.0/views_pipeline_core/data/utils.py +19 -0
  15. views_pipeline_core-0.1.0/views_pipeline_core/evaluation/__init__.py +0 -0
  16. views_pipeline_core-0.1.0/views_pipeline_core/evaluation/metrics.py +150 -0
  17. views_pipeline_core-0.1.0/views_pipeline_core/files/__init__.py +0 -0
  18. views_pipeline_core-0.1.0/views_pipeline_core/files/utils.py +118 -0
  19. views_pipeline_core-0.1.0/views_pipeline_core/logging/__init__.py +0 -0
  20. views_pipeline_core-0.1.0/views_pipeline_core/logging/utils.py +80 -0
  21. views_pipeline_core-0.1.0/views_pipeline_core/managers/__init__.py +0 -0
  22. views_pipeline_core-0.1.0/views_pipeline_core/managers/model_manager.py +438 -0
  23. views_pipeline_core-0.1.0/views_pipeline_core/managers/path_manager.py +858 -0
  24. views_pipeline_core-0.1.0/views_pipeline_core/models/__init__.py +0 -0
  25. views_pipeline_core-0.1.0/views_pipeline_core/models/outputs.py +141 -0
  26. views_pipeline_core-0.1.0/views_pipeline_core/wandb/__init__.py +0 -0
  27. views_pipeline_core-0.1.0/views_pipeline_core/wandb/utils.py +88 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 views platform
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.1
2
+ Name: views_pipeline_core
3
+ Version: 0.1.0
4
+ Summary:
5
+ Author: Borbála Farkas
6
+ Author-email: borbala.farkas@pcr.uu.se
7
+ Requires-Python: >=3.11,<3.15
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Requires-Dist: ingester3 (>=2.1.0,<3.0.0)
13
+ Requires-Dist: properscoring (>=0.1,<0.2)
14
+ Requires-Dist: pytest (>=8.3.3,<9.0.0)
15
+ Requires-Dist: views_forecasts (>=0.5.5,<0.6.0)
16
+ Requires-Dist: viewser (>=6.6.4,<7.0.0)
17
+ Requires-Dist: wandb (>=0.18.7,<0.19.0)
18
+ Description-Content-Type: text/markdown
19
+
20
+ # views_pipeline_core
21
+
22
+ <div style="width: 100%; max-width: 1500px; height: 400px; overflow: hidden; position: relative;">
23
+ <img src="https://pbs.twimg.com/profile_banners/1237000633896652800/1717069203/1500x500" alt="VIEWS Twitter Header" style="position: absolute; top: -50px; width: 100%; height: auto;">
24
+ </div>
25
+
26
+ The [**Violence & Impacts Early Warning System (VIEWS)**](https://viewsforecasting.org/) produces monthly predictions of future violent conflict at both a country and sub-country level of analysis. This repository contains code, configuration files, and documentation that encapsulates the entire process of developing, experimenting, training, evaluating, and deploying the VIEWS machine learning model pipeline.
27
+
28
+ Use our [interactive data dashboard](https://data.viewsforecasting.org/) to explore our latest predictions of future armed conflict.
29
+
30
+ > [!CAUTION]
31
+ > Please note that this pipeline is **actively under construction**. We're in the **early stages of development**, meaning it's **not yet ready for operational use**. We're working hard to bring you a robust and fully-functional tool, so stay tuned for updates!
32
+
33
+ ## Table of contents
34
+
35
+ <!-- toc -->
36
+ - [Repository Contents, Structure, and Explanations](#repository-contents-structure-and-explanations)
37
+ - [Pipeline Execution](#pipeline-execution)
38
+ - [Pipeline Documentation](#pipeline-documentation)
39
+ - [About the VIEWS Project](#about-the-views-project)
40
+
41
+
42
+ <!-- tocstop -->
43
+
44
+
45
+ ## Repository Contents, Structure, and Explanations
46
+ ![VIEWS pipeline diagram](documentation/pipeline_diagram001.png)
47
+
48
+ ### Repository Contents
49
+
50
+ This repository includes:
51
+
52
+ - **Code:** Source code for the VIEWS project's machine learning models and the full pipeline.
53
+ - **Configuration Files:** Settings and configurations for running the models, ensembles, and orchestration scripts.
54
+ - **Documentation:** Detailed instructions and information about the project and how to interact with the pipeline and the individual components.
55
+
56
+ ### Pipeline Overview
57
+
58
+ The VIEWS machine learning pipeline involves several key processes:
59
+
60
+ - **Developing:** Creating and refining machine learning models.
61
+ - **Experimentation:** Testing and validating various model configurations and approaches.
62
+ - **Training:** Training models with relevant data.
63
+ - **Evaluating:** Assessing model performance and accuracy.
64
+ - **Deploying:** Implementing models in a production environment to generate monthly true-future forecasts
65
+
66
+ ## Pipeline Documentation
67
+ High-level documentation on the pipeline and its components can be found in the folder [`documentation`](https://github.com/views-platform/views_pipeline_core/tree/main/documentation). For a comprehensive understanding of the terms and concepts used, please consult the [`Glossary`](https://github.com/views-platform/views_pipeline_core/blob/main/documentation/glossary.md). To explore the rationale behind our architectural choices, visit the [`Architectural Decision Records (ADRs)`](https://github.com/views-platform/views_pipeline_core/blob/main/documentation/ADRs/README.md).
68
+
69
+ Additionally, refer to READMEs and docstrings of various functions and classes in the source code.
70
+
71
+ The operational fatalities model generates forecasts for state-based armed conflict during each month in a rolling 3-year window.
72
+ The latest iteration, currently in production, is called [Fatalities002](https://viewsforecasting.org/early-warning-system/models/fatalities002/).
73
+
74
+ The following links cover **modelling documentation** for Fatalities002:
75
+ - [Prediction models and input variables in main ensemble](https://viewsforecasting.org/views_documentation_models_fatalities002/)
76
+ - [Levels of analysis and dependent variables](https://viewsforecasting.org/wp-content/uploads/VIEWS_documentation_LevelsandOutcomes.pdf)
77
+ - [Partitioning and time shifting data for training, calibration, testing/forecasting, model weighting, and out-of-sample evaluation](https://viewsforecasting.org/wp-content/uploads/VIEWS_Documentation_Partitioningandtimeshifting_Fatalities002.pdf)
78
+ - [Ensembling and calibration](https://viewsforecasting.org/wp-content/uploads/VIEWS_documentation_Ensembling_Fatalities002.pdf)
79
+
80
+ For VIEWS-specific **infrastructure documentation**, please refer to following GitHub repositories:
81
+ - [`ingester3`: Loading input data into the views database](https://github.com/UppsalaConflictDataProgram/ingester3)
82
+ - [`viewser`: Accessing input data from views database](https://github.com/prio-data/viewser)
83
+ - [`views_api`: Our API for accessing predictions](https://github.com/prio-data/views_api)
84
+
85
+ ## About the VIEWS Project
86
+
87
+ The VIEWS project is a collaborative effort supported by leading research institutions focused on peace and conflict studies. For more information about the project, visit the [VIEWS Forecasting webpage](https://viewsforecasting.org/).
88
+
89
+ ### Affiliations
90
+
91
+ - **Peace Research Institute Oslo (PRIO):**
92
+ The [Peace Research Institute Oslo (PRIO)](https://www.prio.org/) conducts research on the conditions for peaceful relations between states, groups, and people. PRIO is dedicated to understanding the processes that lead to violence and those that create sustainable peace. About half of the VIEWS core team is currently located at PRIO.
93
+
94
+ - **Department of Peace and Conflict Research at the University of Uppsala:**
95
+ The [Department of Peace and Conflict Research at the University of Uppsala](https://www.uu.se/en/department/peace-and-conflict-research) is a leading academic institution in the study of conflict resolution, peacebuilding, and security. The department is renowned for its research and education programs aimed at fostering a deeper understanding of conflict dynamics and peace processes. This department also hosts the [Uppsala Conflict Data Program (UCDP)](https://ucdp.uu.se/), a central data source for the VIEWS project. About half of the VIEWS core team is currently located at the University of Uppsala.
96
+
@@ -0,0 +1,76 @@
1
+ # views_pipeline_core
2
+
3
+ <div style="width: 100%; max-width: 1500px; height: 400px; overflow: hidden; position: relative;">
4
+ <img src="https://pbs.twimg.com/profile_banners/1237000633896652800/1717069203/1500x500" alt="VIEWS Twitter Header" style="position: absolute; top: -50px; width: 100%; height: auto;">
5
+ </div>
6
+
7
+ The [**Violence & Impacts Early Warning System (VIEWS)**](https://viewsforecasting.org/) produces monthly predictions of future violent conflict at both a country and sub-country level of analysis. This repository contains code, configuration files, and documentation that encapsulates the entire process of developing, experimenting, training, evaluating, and deploying the VIEWS machine learning model pipeline.
8
+
9
+ Use our [interactive data dashboard](https://data.viewsforecasting.org/) to explore our latest predictions of future armed conflict.
10
+
11
+ > [!CAUTION]
12
+ > Please note that this pipeline is **actively under construction**. We're in the **early stages of development**, meaning it's **not yet ready for operational use**. We're working hard to bring you a robust and fully-functional tool, so stay tuned for updates!
13
+
14
+ ## Table of contents
15
+
16
+ <!-- toc -->
17
+ - [Repository Contents, Structure, and Explanations](#repository-contents-structure-and-explanations)
18
+ - [Pipeline Execution](#pipeline-execution)
19
+ - [Pipeline Documentation](#pipeline-documentation)
20
+ - [About the VIEWS Project](#about-the-views-project)
21
+
22
+
23
+ <!-- tocstop -->
24
+
25
+
26
+ ## Repository Contents, Structure, and Explanations
27
+ ![VIEWS pipeline diagram](documentation/pipeline_diagram001.png)
28
+
29
+ ### Repository Contents
30
+
31
+ This repository includes:
32
+
33
+ - **Code:** Source code for the VIEWS project's machine learning models and the full pipeline.
34
+ - **Configuration Files:** Settings and configurations for running the models, ensembles, and orchestration scripts.
35
+ - **Documentation:** Detailed instructions and information about the project and how to interact with the pipeline and the individual components.
36
+
37
+ ### Pipeline Overview
38
+
39
+ The VIEWS machine learning pipeline involves several key processes:
40
+
41
+ - **Developing:** Creating and refining machine learning models.
42
+ - **Experimentation:** Testing and validating various model configurations and approaches.
43
+ - **Training:** Training models with relevant data.
44
+ - **Evaluating:** Assessing model performance and accuracy.
45
+ - **Deploying:** Implementing models in a production environment to generate monthly true-future forecasts
46
+
47
+ ## Pipeline Documentation
48
+ High-level documentation on the pipeline and its components can be found in the folder [`documentation`](https://github.com/views-platform/views_pipeline_core/tree/main/documentation). For a comprehensive understanding of the terms and concepts used, please consult the [`Glossary`](https://github.com/views-platform/views_pipeline_core/blob/main/documentation/glossary.md). To explore the rationale behind our architectural choices, visit the [`Architectural Decision Records (ADRs)`](https://github.com/views-platform/views_pipeline_core/blob/main/documentation/ADRs/README.md).
49
+
50
+ Additionally, refer to READMEs and docstrings of various functions and classes in the source code.
51
+
52
+ The operational fatalities model generates forecasts for state-based armed conflict during each month in a rolling 3-year window.
53
+ The latest iteration, currently in production, is called [Fatalities002](https://viewsforecasting.org/early-warning-system/models/fatalities002/).
54
+
55
+ The following links cover **modelling documentation** for Fatalities002:
56
+ - [Prediction models and input variables in main ensemble](https://viewsforecasting.org/views_documentation_models_fatalities002/)
57
+ - [Levels of analysis and dependent variables](https://viewsforecasting.org/wp-content/uploads/VIEWS_documentation_LevelsandOutcomes.pdf)
58
+ - [Partitioning and time shifting data for training, calibration, testing/forecasting, model weighting, and out-of-sample evaluation](https://viewsforecasting.org/wp-content/uploads/VIEWS_Documentation_Partitioningandtimeshifting_Fatalities002.pdf)
59
+ - [Ensembling and calibration](https://viewsforecasting.org/wp-content/uploads/VIEWS_documentation_Ensembling_Fatalities002.pdf)
60
+
61
+ For VIEWS-specific **infrastructure documentation**, please refer to following GitHub repositories:
62
+ - [`ingester3`: Loading input data into the views database](https://github.com/UppsalaConflictDataProgram/ingester3)
63
+ - [`viewser`: Accessing input data from views database](https://github.com/prio-data/viewser)
64
+ - [`views_api`: Our API for accessing predictions](https://github.com/prio-data/views_api)
65
+
66
+ ## About the VIEWS Project
67
+
68
+ The VIEWS project is a collaborative effort supported by leading research institutions focused on peace and conflict studies. For more information about the project, visit the [VIEWS Forecasting webpage](https://viewsforecasting.org/).
69
+
70
+ ### Affiliations
71
+
72
+ - **Peace Research Institute Oslo (PRIO):**
73
+ The [Peace Research Institute Oslo (PRIO)](https://www.prio.org/) conducts research on the conditions for peaceful relations between states, groups, and people. PRIO is dedicated to understanding the processes that lead to violence and those that create sustainable peace. About half of the VIEWS core team is currently located at PRIO.
74
+
75
+ - **Department of Peace and Conflict Research at the University of Uppsala:**
76
+ The [Department of Peace and Conflict Research at the University of Uppsala](https://www.uu.se/en/department/peace-and-conflict-research) is a leading academic institution in the study of conflict resolution, peacebuilding, and security. The department is renowned for its research and education programs aimed at fostering a deeper understanding of conflict dynamics and peace processes. This department also hosts the [Uppsala Conflict Data Program (UCDP)](https://ucdp.uu.se/), a central data source for the VIEWS project. About half of the VIEWS core team is currently located at the University of Uppsala.
@@ -0,0 +1,25 @@
1
+ [tool.poetry]
2
+ name = "views_pipeline_core"
3
+ version = "0.1.0"
4
+ description = ""
5
+ authors = [
6
+ "Borbála Farkas <borbala.farkas@pcr.uu.se>",
7
+ "Dylan Pinheiro <dylpin@prio.org>",
8
+ "Xiaolong Sun <xiaolong.sun@pcr.uu.se>"
9
+ ]
10
+ readme = "README.md"
11
+
12
+ [tool.poetry.dependencies]
13
+ python = ">=3.11,<3.15"
14
+ viewser = "^6.6.4"
15
+ pytest = "^8.3.3"
16
+ ingester3 = "^2.1.0"
17
+ views_forecasts = "^0.5.5"
18
+ properscoring = "^0.1"
19
+ wandb = "^0.18.7"
20
+
21
+
22
+
23
+ [build-system]
24
+ requires = ["poetry-core"]
25
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,237 @@
1
+ import pickle
2
+ import os
3
+ import logging
4
+ import sys
5
+ from pathlib import Path
6
+ import threading
7
+ import atexit
8
+ import signal
9
+ from views_pipeline_core.managers.path_manager import ModelPath
10
+ # Configure logging
11
+ logging.basicConfig(
12
+ level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s"
13
+ )
14
+
15
+
16
+ class GlobalCacheMeta(type):
17
+ def __getitem__(cls, key):
18
+ instance = cls()
19
+ return instance[key]
20
+
21
+ def __setitem__(cls, key, value):
22
+ instance = cls()
23
+ instance[key] = value
24
+
25
+ def delete(cls, key):
26
+ instance = cls()
27
+ instance._delete(key)
28
+
29
+ class GlobalCache(metaclass=GlobalCacheMeta):
30
+ """
31
+ A thread-safe singleton cache class that uses a global cache file to store key-value pairs.
32
+
33
+ Attributes:
34
+ _instance (GlobalCache): The singleton instance of the GlobalCache class.
35
+ _lock (threading.Lock): A lock to ensure thread safety.
36
+ filepath (Path): The path to the cache file.
37
+ cache (dict): The in-memory cache dictionary.
38
+ initialized (bool): A flag to check if the instance is initialized.
39
+ """
40
+
41
+ _instance = None
42
+ _lock = threading.Lock()
43
+
44
+ def __new__(cls, *args, **kwargs):
45
+ """
46
+ Ensures that only one instance of the GlobalCache class is created (singleton pattern).
47
+
48
+ Uses double-checked locking to minimize the overhead of acquiring the lock.
49
+ """
50
+ if cls._instance is None:
51
+ with cls._lock:
52
+ if cls._instance is None:
53
+ cls._instance = super(GlobalCache, cls).__new__(cls)
54
+ return cls._instance
55
+
56
+ def __init__(self, filepath=None):
57
+ """
58
+ Initializes the GlobalCache instance.
59
+
60
+ Args:
61
+ filepath (Path, optional): The path to the cache file. Defaults to '.global_cache.pkl' in the project root.
62
+ """
63
+ if not hasattr(self, "initialized"):
64
+ self.local_imports()
65
+ if filepath is None:
66
+ filepath = (
67
+ ModelPath.find_project_root() / ".global_cache.pkl"
68
+ )
69
+ self.filepath = filepath
70
+ self.cache = {}
71
+ self.ensure_cache_file_exists()
72
+ self.load_cache()
73
+ self.initialized = True
74
+
75
+ def __getitem__(self, key):
76
+ """
77
+ Retrieves a value from the cache by key.
78
+
79
+ Args:
80
+ key (str): The key to retrieve the value for.
81
+
82
+ Returns:
83
+ The value associated with the key, or None if the key is not found.
84
+ """
85
+ with self._lock:
86
+ return self.get(key)
87
+
88
+ def __setitem__(self, key, value):
89
+ """
90
+ Sets a value in the cache for a given key.
91
+
92
+ Args:
93
+ key (str): The key to set the value for.
94
+ value: The value to set.
95
+ """
96
+ with self._lock:
97
+ self.set(key, value)
98
+
99
+ def local_imports(self):
100
+ pass
101
+
102
+ def ensure_cache_file_exists(self):
103
+ """
104
+ Ensures that the cache file exists. If it does not exist, creates a new cache file.
105
+ """
106
+ if not self.filepath.exists():
107
+ logging.warning(
108
+ f"Cache file: {self.filepath} does not exist. Creating new cache file..."
109
+ )
110
+ with open(self.filepath, "wb") as f:
111
+ pickle.dump({}, f)
112
+ logging.debug(f"Created new cache file: {self.filepath}")
113
+
114
+ def set(self, key, value):
115
+ """
116
+ Sets a value in the in-memory cache and saves the cache to the file.
117
+
118
+ Args:
119
+ key (str): The key to set the value for.
120
+ value: The value to set.
121
+ """
122
+ self.cache[key] = value
123
+ self.save_cache()
124
+ logging.debug(f"Set key: {key} with value: {value}")
125
+
126
+ def get(self, key):
127
+ """
128
+ Retrieves a value from the in-memory cache by key.
129
+
130
+ Args:
131
+ key (str): The key to retrieve the value for.
132
+
133
+ Returns:
134
+ The value associated with the key, or None if the key is not found.
135
+ """
136
+ self.load_cache()
137
+ value = self.cache.get(key, None)
138
+ logging.debug(f"Get key: {key} returned value: {value}")
139
+ return value
140
+
141
+ def _delete(self, key):
142
+ """
143
+ Deletes a key-value pair from the in-memory cache and saves the cache to the file.
144
+
145
+ Args:
146
+ key (str): The key to delete.
147
+ """
148
+ if key in self.cache:
149
+ del self.cache[key]
150
+ self.save_cache()
151
+ logging.debug(f'Deleted key: {key}')
152
+ else:
153
+ logging.warning(f'Key: {key} not found in cache')
154
+
155
+ def save_cache(self):
156
+ """
157
+ Saves the in-memory cache to the cache file.
158
+ """
159
+ with open(self.filepath, "wb") as f:
160
+ pickle.dump(self.cache, f)
161
+ logging.debug(f"Cache saved to file: {self.filepath}")
162
+
163
+ def load_cache(self):
164
+ """
165
+ Loads the cache from the cache file into the in-memory cache.
166
+ """
167
+ if self.filepath.exists():
168
+ try:
169
+ with open(str(self.filepath), "rb") as f:
170
+ loaded_cache = pickle.loads(f.read())
171
+ if isinstance(loaded_cache, dict):
172
+ self.cache = loaded_cache
173
+ logging.debug(f"Cache loaded from file: {self.filepath}")
174
+ else:
175
+ logging.error(
176
+ f"Loaded cache is not a dictionary. Initializing empty cache."
177
+ )
178
+ self.cache = {}
179
+ except (EOFError, pickle.UnpicklingError) as e:
180
+ logging.error(
181
+ f"Failed to load cache from file: {self.filepath}. Error: {e}"
182
+ )
183
+ self.cache = {}
184
+ else:
185
+ self.cache = {}
186
+ logging.debug(f"Cache file does not exist. Initialized empty cache.")
187
+
188
+
189
+ def cleanup_cache_file():
190
+ """
191
+ Deletes the global cache file upon program termination.
192
+
193
+ This function is registered with the atexit module to ensure that the
194
+ global cache file is deleted when the program exits normally. It acquires
195
+ the lock to ensure thread safety and then checks if the cache file exists.
196
+ If the file exists, it deletes the file and logs the action.
197
+ """
198
+ try:
199
+ # Acquire the lock to ensure thread safety
200
+ with GlobalCache._lock:
201
+ if os.path.exists(GlobalCache().filepath):
202
+ os.remove(GlobalCache().filepath)
203
+ logging.info(f"Cache file: {GlobalCache().filepath} deleted at exit")
204
+ except Exception as e:
205
+ logging.error(f"Error during cleanup: {e}")
206
+
207
+
208
+ def signal_handler(sig, frame):
209
+ """
210
+ Signal handler for SIGINT to delete the cache file upon user interruption.
211
+
212
+ Args:
213
+ sig (int): The signal number.
214
+ frame (FrameType): The current stack frame.
215
+ """
216
+ logging.info("SIGINT received. Deleting cache file...")
217
+ cleanup_cache_file()
218
+ os._exit(0) # Use os._exit to ensure the process exits immediately
219
+
220
+
221
+ # Register the cleanup_cache_file function to be called upon normal program termination
222
+ atexit.register(cleanup_cache_file)
223
+
224
+ # Register the signal handler for SIGINT
225
+ signal.signal(signal.SIGINT, signal_handler)
226
+
227
+
228
+ # if __name__ == '__main__':
229
+ # # Example usage of the GlobalCache class
230
+ # print(GlobalCache["test"]) # Returns None
231
+
232
+ # GlobalCache["test"] = "Hello, World!"
233
+ # print(GlobalCache["test"])
234
+ # GlobalCache.delete("test")
235
+
236
+ # print(GlobalCache["test"]) # Returns None
237
+
@@ -0,0 +1,143 @@
1
+ import sys
2
+ import argparse
3
+
4
+
5
+ def parse_args():
6
+ """
7
+ CLI parser for model specific main.py scripts.
8
+ """
9
+
10
+ parser = argparse.ArgumentParser(
11
+ description="Run model pipeline with specified run type."
12
+ )
13
+
14
+ parser.add_argument(
15
+ "-r",
16
+ "--run_type",
17
+ choices=["calibration", "testing", "forecasting"],
18
+ type=str,
19
+ default="calibration",
20
+ help="Choose the run type for the model: calibration, testing, or forecasting. Default is calibration. "
21
+ "Note: If --sweep is flagged, --run_type must be calibration.",
22
+ )
23
+
24
+ parser.add_argument(
25
+ "-s",
26
+ "--sweep",
27
+ action="store_true",
28
+ help="Set flag to run the model pipeline as part of a sweep. No explicit flag means no sweep."
29
+ "Note: If --sweep is flagged, --run_type must be calibration, and both training and evaluation is automatically implied.",
30
+ )
31
+
32
+ parser.add_argument(
33
+ "-t",
34
+ "--train",
35
+ action="store_true",
36
+ help="Flag to indicate if a new model should be trained. "
37
+ "Note: If --sweep is flagged, --train will also automatically be flagged.",
38
+ )
39
+
40
+ parser.add_argument(
41
+ "-e",
42
+ "--evaluate",
43
+ action="store_true",
44
+ help="Flag to indicate if the model should be evaluated. "
45
+ "Note: If --sweep is specified, --evaluate will also automatically be flagged. "
46
+ "Cannot be used with --run_type forecasting.",
47
+ )
48
+
49
+ parser.add_argument(
50
+ "-f",
51
+ "--forecast",
52
+ action="store_true",
53
+ help="Flag to indicate if the model should produce predictions. "
54
+ "Note: If --sweep is specified, --forecast will also automatically be flagged. "
55
+ "Can only be used with --run_type forecasting.",
56
+ )
57
+
58
+ parser.add_argument(
59
+ "-a",
60
+ "--artifact_name",
61
+ type=str,
62
+ help="Specify the name of the model artifact to be used for evaluation. "
63
+ "The file extension will be added in the main and fit with the specific model algorithm."
64
+ "The artifact name should be in the format: <run_type>_model_<timestamp>.pt."
65
+ "where <run_type> is calibration, testing, or forecasting, and <timestamp> is in the format YMD_HMS."
66
+ "If not provided, the latest artifact will be used by default.",
67
+ )
68
+
69
+ parser.add_argument(
70
+ "-en",
71
+ "--ensemble",
72
+ action="store_true",
73
+ help="Flag to indicate if the model is an ensemble.",
74
+ )
75
+
76
+ parser.add_argument(
77
+ "-sa", "--saved", action="store_true", help="Used locally stored data"
78
+ )
79
+
80
+ parser.add_argument(
81
+ "-o", "--override_month", help="Over-ride use of current month", type=int
82
+ )
83
+
84
+ parser.add_argument(
85
+ "-dd", "--drift_self_test", action="store_true", default=False,
86
+ help="Enable drift-detection self_test at data-fetch"
87
+ )
88
+
89
+ return parser.parse_args()
90
+
91
+
92
+ def validate_arguments(args):
93
+ if args.sweep and args.run_type != "calibration":
94
+ print("Error: Sweep runs must have --run_type set to 'calibration'. Exiting.")
95
+ print("To fix: Use --run_type calibration when --sweep is flagged.")
96
+ sys.exit(1)
97
+
98
+ if args.evaluate and args.run_type == "forecasting":
99
+ print("Error: Forecasting runs cannot evaluate. Exiting.")
100
+ print("To fix: Remove --evaluate flag when --run_type is 'forecasting'.")
101
+ sys.exit(1)
102
+
103
+ if (
104
+ args.run_type in ["calibration", "testing", "forecasting"]
105
+ and not args.train
106
+ and not args.evaluate
107
+ and not args.forecast
108
+ and not args.sweep
109
+ ):
110
+ print(
111
+ f"Error: Run type is {args.run_type} but neither --train, --evaluate, nor --sweep flag is set. Nothing to do... Exiting."
112
+ )
113
+ print(
114
+ "To fix: Add --train and/or --evaluate flag. Or use --sweep to run both training and evaluation in a WadnB sweep loop."
115
+ )
116
+ sys.exit(1)
117
+
118
+ if args.train and args.artifact_name:
119
+ print("Error: Both --train and --artifact_name flags are set. Exiting.")
120
+ print("To fix: Remove --artifact_name if --train is set, or vice versa.")
121
+ sys.exit(1)
122
+
123
+ if args.forecast and args.run_type != "forecasting":
124
+ print(
125
+ "Error: --forecast flag can only be used with --run_type forecasting. Exiting."
126
+ )
127
+ print("To fix: Set --run_type to forecasting if --forecast is flagged.")
128
+ sys.exit(1)
129
+
130
+ if args.ensemble and args.sweep:
131
+ # This is a temporary solution. In the future we might need to train and sweep the ensemble models.
132
+ print(
133
+ "Error: --aggregation flag cannot be used with --sweep. Exiting."
134
+ )
135
+ sys.exit(1)
136
+
137
+ if not args.train and not args.saved:
138
+ # if not training, then we need to use saved data
139
+ print(
140
+ "Error: if --train is not set, you should only use --saved flag. Exiting."
141
+ )
142
+ print("To fix: Add --train or --saved flag.")
143
+ sys.exit(1)
@@ -0,0 +1,35 @@
1
+ drift_detection_partition_dict={
2
+ 'calibration':{
3
+ 'global_missingness': {'threshold': 0.01},
4
+ 'time_missingness': {'threshold': 0.05},
5
+ 'space_missingness': {'threshold': 0.05},
6
+ 'feature_missingness': {'threshold': 0.05},
7
+ 'global_zeros': {'threshold': 0.99},
8
+ 'time_zeros': {'threshold': 0.95},
9
+ 'feature_zeros': {'threshold': 0.95},
10
+ 'standard_partition_length': 30,
11
+ 'test_partition_length': 1
12
+
13
+ },
14
+ 'testing':{
15
+ 'global_missingness': {'threshold': 0.01},
16
+ 'time_missingness': {'threshold': 0.05},
17
+ 'space_missingness': {'threshold': 0.05},
18
+ 'feature_missingness': {'threshold': 0.05},
19
+ 'global_zeros': {'threshold': 0.99},
20
+ 'time_zeros': {'threshold': 0.95},
21
+ 'feature_zeros': {'threshold': 0.95},
22
+ 'standard_partition_length': 30,
23
+ 'test_partition_length': 1
24
+
25
+ },
26
+
27
+ 'forecasting':{
28
+ 'delta_completeness': {'threshold': 0.01},
29
+ 'delta_zeroes': {'threshold': 0.01},
30
+ # 'ks_drift': {'threshold': 100},
31
+ 'extreme_values': {'threshold': 5.0},
32
+ 'standard_partition_length': 30,
33
+ 'test_partition_length': 1
34
+ }
35
+ }