comparison json_to_saqc_config.py @ 1:724dcbb35c9a draft default tip

planemo upload for repository https://github.com/Helmholtz-UFZ/galaxy-tools/blob/main/tools/saqc/ commit b674325a07b6e964e25cd65967149018dc2671fe
author ufz
date Sat, 16 Aug 2025 11:43:23 +0000
parents
children
comparison
equal deleted inserted replaced
0:55bbea0cdc60 1:724dcbb35c9a
1 #!/usr/bin/env python
2
3 import json
4 import math
5 import sys
6
7
8 def format_saqc_value_repr(value: any) -> str:
9 """
10 Konvertiert einen Python-Wert in seine korrekte String-Darstellung für die SaQC-Konfiguration.
11 Behandelt None, Bools, Floats (inkl. inf/nan) und Strings zentral.
12 """
13 if value is None:
14 return "None"
15 if isinstance(value, bool):
16 return str(value)
17 if isinstance(value, float):
18 if math.isinf(value):
19 return "float('inf')" if value > 0 else "float('-inf')"
20 if math.isnan(value):
21 return "float('nan')"
22 return repr(value)
23 if isinstance(value, int):
24 return str(value)
25 if isinstance(value, str):
26 val_lower = value.lower()
27 if val_lower == "inf":
28 return "float('inf')"
29 if val_lower == "-inf":
30 return "float('-inf')"
31 if val_lower == "nan":
32 return "float('nan')"
33 escaped_v = value.replace("\\", "\\\\").replace('"', '\\"')
34 return f'"{escaped_v}"'
35 sys.stderr.write(
36 f"Warning: Unhandled type {type(value)}. Converting to string representation: '{str(value)}'.\n"
37 )
38 return repr(value)
39
40
41 print("varname; function")
42
43 try:
44 infile = sys.argv[1]
45 with open(infile) as fh:
46 params_from_galaxy = json.load(fh)
47 except Exception as e:
48 sys.stderr.write(
49 f"Error opening or reading JSON file {infile}: {type(e).__name__} - {e}\n"
50 )
51 sys.exit(1)
52
53 EMPTY_STRING_IS_NONE_PARAMS = {
54 "xscope",
55 "yscope",
56 "max_gap",
57 "min_periods",
58 "min_residuals",
59 "min_offset",
60 }
61
62 for r_method_set in params_from_galaxy.get("methods_repeat", []):
63 method_str_for_error = "unknown_method_in_repeat"
64 field_str_for_error = "unknown_field_in_repeat"
65 try:
66 method_cond_params = r_method_set.get("module_cond", {}).get("method_cond", {})
67 if not method_cond_params:
68 sys.stderr.write(
69 f"Warning: Skipping a methods_repeat entry due to missing/empty method_cond: {r_method_set}\n"
70 )
71 continue
72
73 params_to_process = method_cond_params.copy()
74
75 method = params_to_process.pop("method_select", "unknown_method")
76 method_str_for_error = method
77
78 raw_field_val = None
79 if "field" in params_to_process:
80 raw_field_val = params_to_process.pop("field")
81 elif "field_repeat" in params_to_process:
82 field_repeat_data = params_to_process.pop("field_repeat", [])
83 if isinstance(field_repeat_data, list) and len(field_repeat_data) > 0:
84 first_field_item = field_repeat_data[0]
85 if isinstance(first_field_item, dict):
86 raw_field_val = first_field_item.get("field")
87
88 if raw_field_val is None or str(raw_field_val).strip() == "":
89 field_str = "undefined_field"
90 field_str_for_error = "undefined_field (extraction failed or empty)"
91 sys.stderr.write(
92 f"Warning: Field name could not be determined for method '{method}'. Using '{field_str}'.\n"
93 )
94 else:
95 field_str = str(raw_field_val) if not isinstance(raw_field_val, list) else ",".join(map(str, raw_field_val))
96 field_str_for_error = field_str
97
98 saqc_args_dict = {}
99 for param_key, param_value_json in params_to_process.items():
100 if param_key.endswith("_select_type"):
101 continue
102
103 actual_param_name_for_saqc = param_key
104 current_value_for_saqc = param_value_json
105
106 if isinstance(param_value_json, dict) and param_key.endswith("_cond"):
107 actual_param_name_for_saqc = param_key[:-5]
108 value_found = False
109 for inner_k, inner_v in param_value_json.items():
110 if not inner_k.endswith("_select_type"):
111 current_value_for_saqc = inner_v
112 value_found = True
113 break
114 if not value_found:
115 current_value_for_saqc = None
116
117 if current_value_for_saqc == "__none__":
118 saqc_args_dict[actual_param_name_for_saqc] = None
119 elif isinstance(current_value_for_saqc, str) and not current_value_for_saqc and actual_param_name_for_saqc in EMPTY_STRING_IS_NONE_PARAMS:
120 saqc_args_dict[actual_param_name_for_saqc] = None
121 else:
122 saqc_args_dict[actual_param_name_for_saqc] = current_value_for_saqc
123 param_strings_for_saqc_call = [
124 f"{k_saqc}={format_saqc_value_repr(v_saqc)}"
125 for k_saqc, v_saqc in sorted(saqc_args_dict.items())
126 ]
127
128 print(
129 f"{field_str}; {method}({', '.join(param_strings_for_saqc_call)})",
130 flush=True,
131 )
132
133 except Exception as e:
134 sys.stderr.write(
135 f"FATAL Error processing a method entry: {type(e).__name__} - {e}\n"
136 )
137 sys.stderr.write(
138 f"Offending entry: {r_method_set}\n"
139 )
140 sys.stderr.write(
141 f"Method context: {method_str_for_error}, Field context: {field_str_for_error}\n"
142 )
143 import traceback
144 traceback.print_exc(file=sys.stderr)
145 print(
146 f"{field_str_for_error}; ERROR_PROCESSING_METHOD({method_str_for_error})",
147 flush=True)
148 continue