Mercurial > repos > muon-spectroscopy-computational-project > muspinsim_config
diff build_file.py @ 3:331d0776abb4 draft
planemo upload for repository https://github.com/muon-spectroscopy-computational-project/muon-galaxy-tools/main/muspinsim_config commit 4f06b404d8b7fb83995f3052faa7e2ec7811f507
author | muon-spectroscopy-computational-project |
---|---|
date | Fri, 03 Feb 2023 15:39:07 +0000 |
parents | c70012022f0f |
children | e1e338f56656 |
line wrap: on
line diff
--- a/build_file.py Thu Sep 15 10:23:52 2022 +0000 +++ b/build_file.py Fri Feb 03 15:39:07 2023 +0000 @@ -11,15 +11,15 @@ :param file_name: name of file :param content: list of strings containing blocks to write """ - with open(file_name, "w") as f: - f.write( + with open(file_name, "w", encoding="utf-8") as file: + file.write( """ ####################################################### -#Muspinsim Input File -#Generated using Muon Galaxy Tool Muspinsim_Input +# Muspinsim Input File +# Generated using Muon Galaxy Tool Muspinsim_Input #######################################################\n\n""" ) - f.write("".join(content)) + file.write("".join(content)) def build_block(title, vals): @@ -47,9 +47,8 @@ elif char == ")": if len(stck) == 0: raise ValueError( - "Could not parse entry {0}" - "brackets mismatch - unexpected ')' " - "found on char {1}".format(entry, i) + f"Could not parse entry {entry} brackets mismatch - " + f"unexpected ')' found on char {i}" ) stck.pop() elif char == " " and len(stck) > 0: @@ -63,10 +62,8 @@ if len(stck) != 0: raise ValueError( - "Could not parse entry {0}" - "brackets mismatch - unclosed '(' found on char(s): {1}".format( - entry, stck - ) + f"Could not parse entry {entry} brackets mismatch - unclosed '(' " + f"found on char(s): {stck}" ) return new_str @@ -92,11 +89,8 @@ chars = [elem.strip() for elem in content if elem != ""] if len(chars) != nargs: raise ValueError( - "Could not parse entry {0}" - " incorrect number of args" - " found {1}:\n({2})\nBut expected {3}".format( - entry, len(chars), chars, nargs - ) + f"Could not parse entry {entry} incorrect number of args found " + f"{len(chars)}:\n({chars})\nBut expected {nargs}" ) return chars @@ -104,7 +98,7 @@ def parse_matrix(entry_string, size): """ Helper function to parse and format matrix/vector - to be readable by Muspinsim + to be readable by MuSpinSim :param entry_string: a user input string for a matrix/vector :param size: (x, y) integer tuple: dimensions of matrix :return: a list of strings of length y, each string @@ -136,31 +130,30 @@ parse_matrix(options["zeeman_vector"], (3, 1)), ), "hyperfine": lambda options: build_block( - "hyperfine {0} {1}".format( - options["hfine_index"], - options["hfine_e_index"] - if options["hfine_e_index"] - else "", + ( + f"hyperfine {options['hfine_index']} " + f"""{ + options['hfine_e_index'] + if options['hfine_e_index'] else '' + }""" ).strip(), parse_matrix(options["hfine_matrix"], (3, 3)), ), "dipolar": lambda options: build_block( - "dipolar {0} {1}".format( - options["di_index"], options["di_index_2"] - ), + f"dipolar {options['di_index']} {options['di_index_2']}", parse_matrix(options["di_vector"], (3, 1)), ), "quadrupolar": lambda options: build_block( - "quadrupolar {0}".format(options["quad_index"]), + f"quadrupolar {options['quad_index']}", parse_matrix(options["quad_matrix"], (3, 3)), ), "dissipation": lambda options: build_block( - "dissipation {0}".format(options["dis_index"]), + f"dissipation {options['dis_index']}", [options["dis_val"]], ), }.get(interaction_type)(options) - except ValueError as e: - raise ValueError("Error occurred when parsing {0}".format(e)) + except ValueError as exc: + raise ValueError(f"Error occurred when parsing {exc}") from exc def parse_orientation(orientation): @@ -217,16 +210,18 @@ return " ".join(split_into_args(options["polarization"], 3)) -def parse_field(field): +def parse_field(field, field_type): """ Helper function to parse field keyword arguments :param field: a dictionary containing one set of field arguments + :param field_type: a string giving the type of field, either field or + intrinsic_field :return: a formatted string """ try: - return " ".join(split_into_args(field["field"], 1)) + return " ".join(split_into_args(field[field_type], 1)) except ValueError: - return " ".join(split_into_args(field["field"], 3)) + return " ".join(split_into_args(field[field_type], 3)) def parse_fitting_variables(fitting_variables): @@ -251,41 +246,62 @@ def parse_spin(spin): + """ + Helper function for parsing a spin + :param spin: a dictionary containing a spin object from the config either + just a spin_preset or a custom value with a name and + atomic_mass + """ if spin["spin_preset"] != "custom": return spin["spin_preset"] else: elem_name = spin["spin"].strip() - if elem_name not in ['e', 'mu']: + if elem_name not in ["e", "mu"]: elem_name = elem_name.capitalize() - return "{0}{1}".format( - int(spin["atomic_mass"]) if spin["atomic_mass"] else "", - elem_name + return ( + f"{int(spin['atomic_mass']) if spin['atomic_mass'] else ''}" + f"{elem_name}" ).strip() +def parse_celio(celio_params): + """ + Helper function for parsing Celio's method parameters + :param celio_params: a dictionary containing the parameters for Celio's + method + """ + options = celio_params["celio_options"] + if not options["celio_enabled"]: + return "" + else: + # Now have celio_k and potentially celio_averages + celio_k = options["celio_k"] + celio_averages = options["celio_averages"] + + # As celio_averages is optional so may be None + if celio_averages is None: + celio_averages = "" + + return build_block("celio", [f"{celio_k} {celio_averages}".strip()]) + + parse_func_dict = { "spins": lambda values: build_block( "spins", - [ - " ".join( - [ - parse_spin(entry["spin_options"]) - for entry in values - ] - ) - ], + [" ".join([parse_spin(entry["spin_options"]) for entry in values])], ), # either 1x3 vector or scalar or function "fields": lambda values: build_block( - "field", [parse_field(entry) for entry in values] + "field", [parse_field(entry, "field") for entry in values] + ), + "intrinsic_fields": lambda values: build_block( + "intrinsic_field", + [parse_field(entry, "intrinsic_field") for entry in values], ), # either scalar or single function "times": lambda values: build_block( "time", - [ - " ".join(split_into_args(entry["time"], 1)) - for entry in values - ], + [" ".join(split_into_args(entry["time"], 1)) for entry in values], ), # either scalar or single function "temperatures": lambda values: build_block( @@ -295,16 +311,21 @@ for entry in values ], ), - "x_axis": lambda value: build_block("x_axis", [value]), - "y_axis": lambda value: build_block("y_axis", [value]), - "average_axes": lambda values: build_block( - "average_axes", values - ), - "experiment_preset": lambda value: build_block( - "experiment", [value] - ), + "axes_options": { + "x_axis_options": { + "x_axis": lambda value: build_block("x_axis", [value]), + "average_axes": lambda values: build_block( + "average_axes", values), + }, + "x_axis": lambda value: build_block("x_axis", [value]), + "y_axis": lambda value: build_block("y_axis", [value]), + "average_axes": lambda values: build_block( + "average_axes", values) + }, + "average_axes": lambda values: build_block("average_axes", values), + "experiment_preset": lambda value: build_block("experiment", [value]), "orientations": lambda values: build_block( - "orientation {0}".format(euler_convention), + f"orientation {EULER_CONVENTION}", [parse_orientation(entry) for entry in values], ), "interactions": lambda values: "".join( @@ -314,12 +335,11 @@ "polarization", [parse_polarization(entry) for entry in values], ), + "celio_params": parse_celio, "fitting": lambda value: build_block( "fitting_data", ['load("fitting_data.dat")'] ), - "fitting_method": lambda value: build_block( - "fitting_method", [value] - ), + "fitting_method": lambda value: build_block("fitting_method", [value]), "fitting_variables": lambda values: build_block( "fitting_variables", [parse_fitting_variables(entry) for entry in values], @@ -329,12 +349,58 @@ [str(value)], ), } -euler_convention = 'ZYZ' +EULER_CONVENTION = "ZYZ" + +# Gives replacement values in the case a parameter is unassigned +parse_none_dict = { + # Allow average_axis to be None as by default is orientation in + # muspinsim but letting the UI present this here instead + "average_axes": ["none"], +} + + +def parse_dict(dictionary, params, file_contents) -> bool: + """ + Helper function for parsing nested dictionaries defined above + containing parse functions + :returns: Whether an error occurred + """ + + err_found = False + for keyword, val in params.items(): + + # Either don't allow the value to be None or replace + # with value in the parse_none_dict above + should_assign = val and val not in ["None"] + if not should_assign and keyword in parse_none_dict: + should_assign = keyword in parse_none_dict + val = parse_none_dict[keyword] + + if should_assign: + try: + keyword_func = dictionary.get(keyword) + # Check for nested dict, and add that contents as well if found + if isinstance(keyword_func, dict): + err_found = err_found or parse_dict( + keyword_func, val, file_contents) + else: + if keyword_func: + file_contents.append(keyword_func(val)) + + except ValueError as exc: + sys.stderr.write( + f"Error occurred when parsing {keyword}\n{str(exc)}" + ) + err_found = True + return err_found def main(): + """ + Entry point + """ input_json_path = sys.argv[1] - mu_params = json.load(open(input_json_path, "r")) + mu_params = json.load(open(input_json_path, "r", encoding="utf-8")) out_file_name = mu_params["out_file_prefix"].strip().replace(" ", "_") @@ -354,41 +420,24 @@ del mu_params["experiment_preset"] del mu_params["experiment"] - global euler_convention - euler_convention = mu_params["euler_convention"] + global EULER_CONVENTION + EULER_CONVENTION = mu_params["euler_convention"] - err_found = False file_contents = [ build_block("name", [out_file_name.strip().replace(" ", "_")]) ] - for keyword, val in mu_params.items(): - if val and val not in ["None"]: - try: - keyword_func = parse_func_dict.get(keyword) - if keyword_func: - file_contents.append(keyword_func(val)) - except ValueError as e: - sys.stderr.write( - "Error occurred when parsing {0}\n{1}".format( - keyword, str(e) - ) - ) - err_found = True - - if err_found: + if parse_dict(parse_func_dict, mu_params, file_contents): sys.exit(1) write_file("outfile.in", file_contents) try: - MuSpinInput(open("outfile.in")) - except Exception as e: + MuSpinInput(open("outfile.in", encoding="utf-8")) + except Exception as exc: # pylint: disable=broad-except sys.stdout.write( - "Warning, This created file may not work properly. " - "Error(s) encountered when trying to parse the file : {0}".format( - str(e) - ) + "Warning, This created file may not work properly. Error(s) " + f"encountered when trying to parse the file : {str(exc)}" ) sys.exit(1)