1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
import json
import os
import sys
import warnings
def read_input(path=""):
"""
Reads and processes the input JSON file from the specified path. Validates the input path,
ensures the file exists, and decodes the JSON content. Switches to the project root directory
before returning the parsed input.
:param path: The relative path to the input JSON file.
:type path: str
:raises ValueError: If the input path is not provided, file does not exist, or JSON decoding fails.
:return: Parsed JSON content.
:rtype: dict
:side effect: Changes the working directory to the project root.
"""
if not path:
raise ValueError("No input path provided.")
path = path.strip().strip(',')
project_root = find_root_dir()
if not project_root:
raise ValueError("Project root not found.")
full_path = os.path.join(project_root, path)
if not os.path.exists(full_path):
raise ValueError(f"File does not exist: {full_path}")
try:
with open(full_path, 'r') as raw_json:
input_json = json.load(raw_json)
except json.JSONDecodeError:
raise ValueError("Failed to decode JSON.")
except IOError:
raise ValueError("MultiModel's parser says: Error opening file.")
switch_to_root_dir()
# Validate and apply defaults
input_json = parse_input(input_json)
return input_json
def parse_input(input_json):
"""
Validates and applies default values to the input JSON content. Ensures required fields are present
and raises warnings or errors for missing or invalid values.
:param input_json: The input JSON content.
:type input_json: dict
:raises ValueError: If required fields are missing or invalid values are provided.
:return: Validated and processed JSON content with defaults applied.
:rtype: dict
"""
DEFAULTS = {
"multimodel": True,
"metamodel": False,
"window_size": 1,
"window_function": "mean",
"meta_function": "mean",
"samples_per_minute": 0,
"current_unit": "",
"unit_scaling_magnitude": 1,
"plot_type": "time_series",
"plot_title": "",
"x_label": "",
"y_label": "",
"seed": 0,
"y_ticks_count": None,
"x_ticks_count": None,
"y_min": None,
"y_max": None,
"x_min": None,
"x_max": None,
}
# Apply default values where not specified
for key, default_value in DEFAULTS.items():
if key not in input_json:
input_json[key] = default_value
# Special handling for required fields without default values
if "metric" not in input_json:
raise ValueError("Required field 'metric' is missing.")
if ("meta_function" not in input_json) and input_json["metamodel"]:
raise ValueError("Required field 'meta_function' is missing. Please select between 'mean' and 'median'. Alternatively,"
"disable metamodel in the config file.")
if input_json["meta_function"] not in ["mean", "median", "meta_equation1", "equation2", "equation3"]:
raise ValueError("Invalid value for meta_function. Please select between 'mean', 'median', !!!!!!!to be updated in the end!!!!!!!!.")
# raise a warning
if not input_json["multimodel"] and input_json["metamodel"]:
warnings.warn("Warning: Cannot have a Meta-Model without a Multi-Model. No computation made.")
return input_json
def find_root_dir():
"""
Searches for the project root directory by looking for a 'README.md' file in the current
and parent directories.
:return: The path to the project root directory if found, otherwise None.
:rtype: str or None
"""
current_dir = os.path.dirname(os.path.abspath(__file__))
root = os.path.abspath(os.sep)
while current_dir and current_dir != root:
if os.path.exists(os.path.join(current_dir, 'README.md')):
return current_dir
current_dir = os.path.dirname(current_dir)
return None
def switch_to_root_dir():
"""
Switches the current working directory to the project root directory. Exits the program if the
root directory is not found.
:side effect: Changes the current working directory or exits the program.
"""
root_dir = find_root_dir()
if root_dir:
os.chdir(root_dir)
else:
print("Failed to switch to root directory.")
sys.exit(1)
|