Mercurial > repos > ufz > saqc
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 |
