Mercurial > repos > muon-spectroscopy-computational-project > muspinsim_config
changeset 0:c70012022f0f draft
planemo upload for repository https://github.com/muon-spectroscopy-computational-project/muon-galaxy-tools/main/muspinsim_config commit d130cf2c46d933fa9d0214ddbd5ddf860f322dc4
author | muon-spectroscopy-computational-project |
---|---|
date | Thu, 25 Aug 2022 16:16:47 +0000 |
parents | |
children | 844b73d2f40c |
files | build_file.py muspinsim_config.xml sample_fitting_data.dat test-data/test_1.in test-data/test_2.in test-data/test_3.in test-data/test_4.in test-data/test_5.in |
diffstat | 8 files changed, 1025 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build_file.py Thu Aug 25 16:16:47 2022 +0000 @@ -0,0 +1,397 @@ +import json +import re +import sys + +from muspinsim import MuSpinInput + + +def write_file(file_name, content): + """ + Write muspinsim file + :param file_name: name of file + :param content: list of strings containing blocks to write + """ + with open(file_name, "w") as f: + f.write( + """ +####################################################### +#Muspinsim Input File +#Generated using Muon Galaxy Tool Muspinsim_Input +#######################################################\n\n""" + ) + f.write("".join(content)) + + +def build_block(title, vals): + """ + Build keyword block + :param title: string - Keyword + :param vals: list of strings - lines containing values for keyword + :return: A string containing formatted keyword block + """ + return "{0}\n {1}\n".format(title, "\n ".join(vals)) + + +def format_entry(entry): + """ + Helper function to remove whitespace between function parameters + and remove ',' or ';' inbetween parameters + :param entry: string - user entry + :return: string containing only valid parameters + """ + stck = [] + new_str = "" + for i, char in enumerate(entry): + if char == "(": + stck.append(i) + elif char == ")": + if len(stck) == 0: + raise ValueError( + "Could not parse entry {0}" + "brackets mismatch - unexpected ')' " + "found on char {1}".format(entry, i) + ) + stck.pop() + elif char == " " and len(stck) > 0: + continue + + # remove ',' between functions + elif char in [",", ";"] and len(stck) == 0: + new_str += " " + continue + new_str += char + + if len(stck) != 0: + raise ValueError( + "Could not parse entry {0}" + "brackets mismatch - unclosed '(' found on char(s): {1}".format( + entry, stck + ) + ) + return new_str + + +def split_into_args(entry, nargs=1): + """ + Helper function to split input into a list of args + :param entry: a string containing a user inputted line + :param nargs: number of expected arguments + :return: a list of arguments found + :exception: ValueError - if number of arguments + found does not match expected (nargs) + """ + + # remove square brackets and extra whitespace/newline + content = " ".join(entry.replace("[", "").replace("]", "").split()) + + # remove whitespace in between expressions/functions + # remove commas/semicolons in between expressions/functions + # split on whitespace to separate args + + content = re.split(r"\s", format_entry(content)) + 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 + ) + ) + return chars + + +def parse_matrix(entry_string, size): + """ + Helper function to parse and format matrix/vector + 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 + containing x elements (space separated) + """ + content = split_into_args(entry_string, nargs=size[0] * size[1]) + return [ + " ".join(content[x: x + size[0]]) + for x in range(0, len(content), size[0]) + ] + + +def parse_interactions(interaction): + """ + Helper function to build keyword blocks for all + interaction parameters entered + (hyperfine, zeeman, dipolar, quadrupolar and dissipation) + + :param interaction: a dictionary containing all interaction parameters + :return: a string containing several formatted blocks + """ + + options = interaction["interaction_options"] + interaction_type = options["interaction"] + try: + return { + "zeeman": lambda options: build_block( + "zeeman {0}".format(options["zeeman_index"]), + 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 "", + ).strip(), + parse_matrix(options["hfine_matrix"], (3, 3)), + ), + "dipolar": lambda options: build_block( + "dipolar {0} {1}".format( + 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"]), + parse_matrix(options["quad_matrix"], (3, 3)), + ), + "dissipation": lambda options: build_block( + "dissipation {0}".format(options["dis_index"]), + [options["dis_val"]], + ), + }.get(interaction_type)(options) + except ValueError as e: + raise ValueError("Error occurred when parsing {0}".format(e)) + + +def parse_orientation(orientation): + """ + Helper function to parse orientation keyword arguments + :param orientation: a dictionary containing one set of + orientation arguments + :return: a formatted string + """ + + options = orientation["orientation_options"] + preset = options["orientation_preset"] + + return { + "zcw": lambda options: "zcw({0})".format( + " ".join(split_into_args(options["zcw_n"], 1)) + ), + "eulrange": lambda options: "eulrange({0})".format( + " ".join(split_into_args(options["eul_n"], 1)) + ), + "2_polar": lambda options: "{0} {1}".format( + " ".join(split_into_args(options["theta"], 1)), + " ".join(split_into_args(options["phi"], 1)), + ), + "3_euler": lambda options: "{0} {1} {2}".format( + " ".join(split_into_args(options["eul_1"], 1)), + " ".join(split_into_args(options["eul_2"], 1)), + " ".join(split_into_args(options["eul_3"], 1)), + ), + "4_euler": lambda options: "{0} {1} {2} {3}".format( + " ".join(split_into_args(options["eul_1"], 1)), + " ".join(split_into_args(options["eul_2"], 1)), + " ".join(split_into_args(options["eul_3"], 1)), + options["weight"], + ), + }.get(preset)(options) + + +def parse_polarization(polarization): + """ + Helper function to parse polarization keyword arguments + :param polarization: a dictionary containing one set + of polarization arguments + :return: a formatted string + """ + options = polarization["polarization_options"] + preset = options["polarization_preset"] + if preset != "custom": + return preset + else: + try: + return " ".join(split_into_args(options["polarization"], 1)) + except ValueError: + return " ".join(split_into_args(options["polarization"], 3)) + + +def parse_field(field): + """ + Helper function to parse field keyword arguments + :param field: a dictionary containing one set of field arguments + :return: a formatted string + """ + try: + return " ".join(split_into_args(field["field"], 1)) + except ValueError: + return " ".join(split_into_args(field["field"], 3)) + + +def parse_fitting_variables(fitting_variables): + """ + Helper function to parse field keyword fitting_variables + :param fitting_variables: a dictionary containing one set of + arguments + :return: a formatted string + """ + return "{0} {1} {2} {3}".format( + fitting_variables["var_name"].strip().replace(" ", "_"), + " ".join(split_into_args(fitting_variables["start_val"], 1)) + if fitting_variables["start_val"].strip() != "" + else "", + " ".join(split_into_args(fitting_variables["min_bound"], 1)) + if fitting_variables["min_bound"].strip() != "" + else "", + " ".join(split_into_args(fitting_variables["max_bound"], 1)) + if fitting_variables["max_bound"].strip() != "" + else "", + ).strip() + + +def parse_spin(spin): + if spin["spin_preset"] != "custom": + return spin["spin_preset"] + else: + elem_name = spin["spin"].strip() + 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 + ).strip() + + +parse_func_dict = { + "spins": lambda values: build_block( + "spins", + [ + " ".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] + ), + # either scalar or single function + "times": lambda values: build_block( + "time", + [ + " ".join(split_into_args(entry["time"], 1)) + for entry in values + ], + ), + # either scalar or single function + "temperatures": lambda values: build_block( + "temperature", + [ + " ".join(split_into_args(entry["temperature"], 1)) + 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] + ), + "orientations": lambda values: build_block( + "orientation {0}".format(euler_convention), + [parse_orientation(entry) for entry in values], + ), + "interactions": lambda values: "".join( + [parse_interactions(entry) for entry in values] + ), + "polarizations": lambda values: build_block( + "polarization", + [parse_polarization(entry) for entry in values], + ), + "fitting": lambda value: build_block( + "fitting_data", ['load("fitting_data.dat")'] + ), + "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], + ), + "fitting_tolerance": lambda value: build_block( + "fitting_tolerance", + [str(value)], + ), +} +euler_convention = 'ZYZ' + + +def main(): + input_json_path = sys.argv[1] + mu_params = json.load(open(input_json_path, "r")) + + out_file_name = mu_params["out_file_prefix"].strip().replace(" ", "_") + + # combine all sections + mu_params = { + **mu_params["spins"], + **mu_params["interaction_params"], + **mu_params["experiment_params"], + **mu_params["fitting_params"]["fitting_options"], + } + + # get experiment parameters + experiment = mu_params["experiment"] + mu_params = {**mu_params, **experiment} + + if experiment["experiment_preset"] == "custom": + del mu_params["experiment_preset"] + del mu_params["experiment"] + + 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: + sys.exit(1) + + write_file("outfile.in", file_contents) + + try: + MuSpinInput(open("outfile.in")) + except Exception as e: + sys.stdout.write( + "Warning, This created file may not work properly. " + "Error(s) encountered when trying to parse the file : {0}".format( + str(e) + ) + ) + sys.exit(1) + + +if __name__ == "__main__": + main()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/muspinsim_config.xml Thu Aug 25 16:16:47 2022 +0000 @@ -0,0 +1,493 @@ +<tool id="muspinsim_config" name="MuSpinSim Configure" version="@TOOL_VERSION@+galaxy@WRAPPER_VERSION@" python_template_version="3.5" profile="22.01"> + <description>define simulation parameters</description> + <macros> + <!-- version of underlying tool (PEP 440) --> + <token name="@TOOL_VERSION@">1.1.0</token> + <!-- version of this tool wrapper (integer) --> + <token name="@WRAPPER_VERSION@">0</token> + <!-- citation should be updated with every underlying tool version --> + <!-- typical fields to update are version, month, year, and doi --> + <token name="@TOOL_CITATION@"> + @software{muspinsim, + author = {Sturniolo, Simone and Liborio, Leandro and Owen, Josh and Mudaraddi, Anish and {Muon Spectroscopy Computational Project}}, + license = {MIT}, + title = {{muspinsim}}, + url = {https://github.com/muon-spectroscopy-computational-project/muspinsim}, + version = {v1.1.0}, + month = {5}, + year = {2022}, + doi = {10.5281/zenodo.6563074} + } + </token> + </macros> + <creator> + <person givenName="Anish" familyName="Mudaraddi" identifier="https://orcid.org/0000-0002-2135-2705"/> + <person givenName="Eli" familyName="Chadwick" url="https://github.com/elichad" identifier="https://orcid.org/0000-0002-0035-6475"/> + <organization url="https://muon-spectroscopy-computational-project.github.io/index.html" name="The Muon Spectroscopy Computational Project"/> + </creator> + <requirements> + <requirement type="package" version="@TOOL_VERSION@">muspinsim</requirement> + </requirements> + <command detect_errors="exit_code"><![CDATA[ + cp ${__tool_directory__}/sample_fitting_data.dat ./fitting_data.dat && + python ${__tool_directory__}/build_file.py inputs.json + ]]></command> + <configfiles> + <inputs name="inputs" filename="inputs.json" /> + </configfiles> + <inputs> + <param type="text" name="out_file_prefix" label="Name" help="A name with which to label this configuration" optional="true" value="muspinsim" /> + <section name="spins" expanded="true" title="Spins"> + <repeat name="spins" title="Spins to simulate" min="1" help="Specify the spins to be used in the system. This should include a muon (mu) and one or more electrons (e)"> + <conditional name="spin_options"> + <param name="spin_preset" type="select" value="mu" label="Species" help="Select 'custom' to define own"> + <option selected="true" value="mu">mu</option> + <option value="e">e</option> + <option value="custom">custom</option> + </param> + <when value="custom"> + <param name="spin" optional="false" type="text" label="Species name"/> + <param name="atomic_mass" optional="true" type="integer" min="0" value="" label="Atomic mass" help="Leave blank to use default mass - whole numbers only"/> + </when> + <when value="mu"/> + <when value="e"/> + </conditional> + </repeat> + </section> + <section name="interaction_params" expanded="true" title="Spin Interactions" help=""> + <repeat name="interactions" title="Interactions to simulate" help="Add couplings between spins, and/or dissipation terms. Interaction terms available: Zeeman, hyperfine, dipolar, quadrupolar or dissipation. See muspinsim docs for more info"> + <conditional name="interaction_options"> + <param name="interaction" type="select" label="Choose interaction type"> + <option value="zeeman">Zeeman</option> + <option value="hyperfine">hyperfine</option> + <option value="dipolar">dipolar</option> + <option value="quadrupolar">quadrupolar</option> + <option value="dissipation">dissipation</option> + </param> + <when value="zeeman"> + <param name="zeeman_index" type="integer" value="" label="Index of coupled spin" min="1" + help="Index refers to the order of the spins listed in 'spins' section. The first spin in the list has index 1, the second has index 2, and so on."/> + <param name="zeeman_vector" type="text" value="" label="Zeeman coupling vector" + help="Define 1X3 vector for local magnetic field coupling (T). + Allows default expressions, constants and functions (see help)"/> + </when> + <when value="hyperfine"> + <param name="hfine_index" type="integer" value="" label="Index of nuclear coupled spin" min="1" + help="Non-electronic spin - muon or otherwise. + Index refers to the order of the spins listed in 'spins' section. The first spin in the list has index 1, the second has index 2, and so on."/> + <param name="hfine_e_index" type="integer" value="" optional="true" min="1" label="Index of electronic coupled spin" + help="Optional, will use first defined electronic spin if unspecified"/> + <param name="hfine_matrix" area="true" type="text" value="" label="Hyperfine coupling tensor" + help="Define 3X3 tensor for coupling between electron and non-electron spins (in MHz). + Allows default expressions, constants and functions (see help)"> + <sanitizer> + <valid initial="string.printable"> + </valid> + </sanitizer> + </param> + </when> + <when value="dipolar"> + <param name="di_index" type="integer" value="" min="1" label="Index of 1st coupled spin" + help="Index refers to the order of the spins listed in 'spins' section. The first spin in the list has index 1, the second has index 2, and so on."/> + <param name="di_index_2" type="integer" value="" label="Index of 2nd coupled spin" + help="Index refers to the order of the spins listed in 'spins' section. The first spin in the list has index 1, the second has index 2, and so on."/> + <param name="di_vector" type="text" value="" label="Dipole coupling vector" + help="Define 1X3 vector for coupling between two spins (Angstrom). + Allows default expressions, constants and functions (see help)"/> + </when> + <when value="quadrupolar"> + <param name="quad_index" type="integer" value="" label="Index of coupled spin" + help="Index refers to the order of the spins listed in 'spins' section. The first spin in the list has index 1, the second has index 2, and so on."/> + <param name="quad_matrix" area="true" type="text" value="" label="Electric Field Gradient tensor" + help="Define 3X3 tensor (in atomic units) for quadrupolar coupling. + Allows default expressions, constants and functions (see help). + Warning: spins with zero quadrupole moment will have zero coupling regardless of the input"> + <sanitizer> + <valid initial="string.printable"> + </valid> + </sanitizer> + </param> + </when> + <when value="dissipation"> + <param name="dis_index" type="integer" value="" label="Index of spin with dissipation" + help="Index refers to the order of the spins listed in 'spins' section. The first spin in the list has index 1, the second has index 2, and so on."/> + <param name="dis_val" type="text" value="" label="Dissipation" + help="Define dissipation term (MHz). + Allows default expressions, constants and functions (see help)"/> + </when> + </conditional> + </repeat> + </section> + <section name="experiment_params" expanded="true" title="Experiment Parameters"> + <conditional name="experiment"> + <param name="experiment_preset" type="select" value='custom' display="radio" label="Experiment type" + help="Experiment preset to use. Avoided Level Crossing (ALC): sets polarization to longitudinal, x-axis to field and y-axis to integral. + Zero field: sets polarization to transverse and field to 0. Choose custom for no preset"> + <option value="alc">Avoided Level Crossing (ALC)</option> + <option value="zero_field">Zero Field</option> + <option selected="true" value="custom">Custom</option> + </param> + <when value="alc"> + <repeat name="fields" title="Fields" help="Magnetic fields"> + <param name="field" type="text" value="0" label="Field" + optional="true" help="Optional, (default is 0). + Accepts 1X3 vector, or scalar value. Scalar value means field is assumed to be aligned with z axis. + Allows default expressions, constants and functions, plus MHz, muon_gyr constants and special 'range()' function (see help section)"/> + </repeat> + </when> + <when value="zero_field"> + <param name="x_axis" type="select" value="time" display="radio" label="X axis" + help="Range to use as X axis for output file(s)"> + <option selected="true" value="time">time</option> + <option value="field">field</option> + </param> + <param name="y_axis" type="select" value="asymmetry" display="radio" label="Y axis" + help="Range to use as y axis for output file(s) + Asymmetry: use muon's polarization. + Integral: use muon's polarization integral over time. + WARNING: if integral chosen, 'time' parameter is ignored, and cannot be used as x-axis parameter "> + <option value="integral">integral</option> + <option selected="true" value="asymmetry">asymmetry</option> + </param> + </when> + <when value="custom"> + <param name="x_axis" type="select" value="time" display="radio" label="X axis" + help="Range to use as X axis for output file(s)"> + <option selected="true" value="time">time</option> + <option value="field">field</option> + </param> + <param name="y_axis" type="select" value="asymmetry" display="radio" label="Y axis" + help="Range to use as y axis for output file(s) + Asymmetry: use muon's polarization. + Integral: use muon's polarization integral over time. + WARNING: if integral chosen, 'time' parameter is ignored, and cannot be used as x-axis parameter "> + <option value="integral">integral</option> + <option selected="true" value="asymmetry">asymmetry</option> + </param> + <repeat name="fields" title="Fields" help="Magnetic fields"> + <param name="field" type="text" value="0" label="Field (T)" + optional="true" help="Optional, (default is 0). + Accepts 1X3 vector, or scalar value. Scalar value means field is assumed to be aligned with z axis. + Allows default expressions, constants and functions, plus MHz, muon_gyr constants and special 'range()' function (see help section)"/> + </repeat> + <repeat name="polarizations" title="Polarizations" help="The direction along which the muon + should be polarized when starting, as well as the one in which it will be measured. + Each entry will generate a separate calculation when muspinsim is run"> + <conditional name="polarization_options"> + <param name="polarization_preset" value="custom" type="select" display="radio" label="Polarization" + help="transverse: along x-axis, longitudinal: along z-axis, custom: define vector"> + <option value="longitudinal">longditudinal</option> + <option value="transverse">transverse</option> + <option selected="true" value="custom">custom</option> + </param> + <when value="custom"> + <param name="polarization" type="text" value="" label="Enter custom vector for polarization" + help="Accepts 1X3 vector. + Allows default expressions, constants and functions (see help section)"/> + </when> + <when value="longitudinal" /> + <when value="transverse" /> + </conditional> + </repeat> + </when> + </conditional> + <param name="average_axes" type="select" display="checkboxes" multiple="true" optional="true" value="orientation" label="Average axes" + help="Keywords that should have an average carried out over them. Each keyword ticked should have a range specified. + Keywords not ticked or set as X axis, but which have a range set, will generate separate calculations for each value in the range when muspinsim is run."> + <option selected="true" value="orientation">orientation</option> + <option value="polarization">polarization</option> + <option value="field">field</option> + <option value="time">time</option> + <option value="temperature">temperature</option> + </param> + <repeat name="orientations" title="Orientations" help="Orientations to use for crystallites - (define powder averages)"> + <conditional name="orientation_options"> + <param name="orientation_preset" type="select" display="radio" label="Orientation" optional="false" + help="Polar angles: Define two polar angles θ and ϕ, defining only the direction of the z-axis (recommended for powder averages). + Euler angles: Define 3 Euler angles defining a new frame, convention used is ZYZ by default. + Euler angles with weight: define 3 Euler angles and a weight (will be normalized automatically). + Euler angles helper function: eulrange(n). + Zaremba-Conroy-Wolfsberg helper function: zcw(n)"> + <option value="2_polar">Polar angles</option> + <option value="3_euler">Euler angles</option> + <option value="4_euler">Euler angles with weight</option> + <option value="eulrange">Euler angles helper function (eulrange(n))</option> + <option selected="true" value="zcw">Zaremba-Conroy-Wolfsberg helper function (zcw(n))</option> + </param> + <when value="eulrange"> + <param name="eul_n" type="text" value="0" label="n" + help="value for n for eulrange(n), + Allows default expressions, constants and functions. + WARNING: large values are more computationally expensive." + /> + </when> + <when value="zcw"> + <param name="zcw_n" type="text" value="0" label="n" + help="value for n for zcw(n) + Allows default expressions, constants and functions. + WARNING: large values are more computationally expensive." + /> + </when> + <when value="2_polar"> + <param name="theta" type="text" value="" label="θ (theta/inclination) angle" + help="All polar angle entries allow default expressions, constants and functions"/> + <param name="phi" type="text" value="" label="ϕ (phi/azimuth) angle" + help="All polar angle entries allow default expressions, constants and functions"/> + </when> + <when value="3_euler"> + <param name="eul_1" type="text" value="" label="Euler angle 1" + help="All Euler angle entries allow default expressions, constants and functions"/> + <param name="eul_2" type="text" value="" label="Euler angle 2" + help="All Euler angle entries allow default expressions, constants and functions"/> + <param name="eul_3" type="text" value="" label="Euler angle 3" + help="All Euler angle entries allow default expressions, constants and functions"/> + + </when> + <when value="4_euler"> + <param name="eul_1" type="text" value="" label="Euler angle 1" + help="All Euler angle entries allow default expressions and constants"/> + <param name="eul_2" type="text" value="" label="Euler angle 2" + help="All Euler angle entries allow default expressions and constants"/> + <param name="eul_3" type="text" value="" label="Euler angle 3" + help="All Euler angle entries allow default expressions and constants"/> + <param name="weight" type="float" value="0" label="Weight" + help="Allows only floating point value, weights will automatically be normalised"/> + </when> + </conditional> + </repeat> + <param name="euler_convention" type="select" display="radio" label="Euler Convention" + help="Euler angle convention to use for orientation definitions (ignored if Euler angles not defined)"> + <option selected="true" value="zyz">ZYZ</option> + <option value="zxz">ZXZ</option> + </param> + <repeat name="times" title="Time" help="A time or range of times (μs)"> + <param name="time" type="text" label="Time" + help="Either a single time value or `range` function + Allows default expressions, default constants, and special 'range()' function (see help section)" + optional="true" value="range(0, 10, 101)"/> + </repeat> + <repeat name="temperatures" title="Temperature" help="Temperature or range of temperatures (K)"> + <param name="temperature" type="text" + help="Either single value or 'range()' function + Allows default expressions, default constants, and special 'range()' function (see help section). + Warning: both density matrices and dissipative couplings for finite temperatures are only calculated approximatively, see muspinsim docs." + optional="true" value="inf"/> + </repeat> + </section> + <section name="fitting_params" expanded="true" title="Fitting Parameters"> + <conditional name="fitting_options"> + <param name="fitting" type="select" display="radio" optional="false" value="" label="Fit experimental data with simulations" + help="Fitting requires a file with data to fit. File must be given in muspinsim tool, or by manually setting filepath for keyword 'fitting_data' if running muspinsim externally"> + <option value="true">Yes</option> + <option selected="true" value="">No</option> + </param> + <when value="true"> + <param name="fitting_method" type="select" display="radio" optional="false" value="nelder-mead" label="Method to use to fit the data" + help="See the help section for a description of each method"> + <option selected="true" value="nelder-mead">Nelder-Mead</option> + <option value="lbfgs">L-BFGS</option> + </param> + <repeat name="fitting_variables" title="Variable to fit to the experimental data"> + <param name="var_name" type="text" optional="false" label="Name of the variable"/> + <param name="start_val" type="text" value="0" label="Starting value" + help="Allows default expressions, constants and functions, plus MHz, muon_gyr constants. Cannot contain names of other variables"/> + <param name="min_bound" type="text" value="-inf" label="minimum bound" + help="Allows default expressions, constants and functions, plus MHz, muon_gyr constants"/> + <param name="max_bound" type="text" value="inf" label="maximum bound" + help="Allows default expressions, constants and functions, plus MHz, muon_gyr constants"/> + </repeat> + <param name="fitting_tolerance" type="float" optional='true' value="" label="Fitting Tolerance" + help="Used as the tol parameter in Scipy's scipy.optimize.minimize method. Will use scipy defaults if left blank. + Does not accept expressions/functions/constants" + /> + </when> + <when value=""/> + </conditional> + </section> + </inputs> + <outputs> + <data format="txt" label="muspinsim input file $out_file_prefix" name="out_file" from_work_dir="outfile.in" /> + </outputs> + <tests> + <test> + <param name="out_file_prefix" value="test_1"/> + <param name="spin_preset" value="custom"/> + <param name="spin" value="H"/> + <param name="spin_preset" value="mu"/> + <param name="interaction" value="zeeman"/> + <param name="zeeman_index" value="1" /> + <param name="zeeman_vector" value="1 0 0" /> + <param name="zeeman_index" value="2" /> + <param name="zeeman_vector" value="2 0 0" /> + <output name="out_file" file="test_1.in" ftype="txt" compare="diff" /> + </test> + <test> + <param name="out_file_prefix" value="test_2"/> + <param name="spin_preset" value="e"/> + <param name="spin_preset" value="mu"/> + <param name="interaction" value="hyperfine"/> + <param name="hfine_index" value="1" /> + <param name="hfine_matrix" value="[1 0 0 sin(10) (5*2) 0 10*pi 5 cos(20)]"/> + <param name="time" value="range(0, 0.1)" /> + <param name="y_axis" value="asymmetry" /> + <param name="field" value="1.0" /> + <param name="temperature" value="1.0" /> + <output name="out_file" file="test_2.in" ftype="txt" compare="diff" /> + </test> + <test> + <param name="out_file_prefix" value="test_3"/> + <param name="spin_preset" value="custom"/> + <param name="spin" value="H"/> + <param name="spin_preset" value="mu"/> + <param name="spin_preset" value="e"/> + <param name="interaction" value="hyperfine"/> + <param name="hfine_index" value="2" /> + <param name="hfine_matrix" value="[580 5 10 5 580 9 10 9 580]"/> + <param name="interaction" value="hyperfine"/> + <param name="hfine_index" value="3" /> + <param name="hfine_matrix" value="[(300/2) 3 4*10 ], [3 15*10 6-3+2] ,[4 5 15 ]"/> + <param name="average_axes" value="polarization,temperature" /> + <param name="experiment_preset" value="alc" /> + <param name="field" value="range(1.8, 2.6, 100)" /> + <param name="orientation_preset" value="zcw" /> + <param name="zcw_n" value="20" /> + <output name="out_file" file="test_3.in" ftype="txt" compare="diff" /> + </test> + <test> + <param name="out_file_prefix" value="test_4"/> + <param name="spin_preset" value="custom"/> + <param name="spin" value="F"/> + <param name="spin_preset" value="custom"/> + <param name="spin" value="F"/> + <param name="spin_preset" value="mu"/> + <param name="interaction" value="dipolar"/> + <param name="di_index" value="1"/> + <param name="di_index_2" value="2"/> + <param name="di_vector" value="0.9 0.9 0"/> + <param name="interaction" value="dipolar"/> + <param name="di_index" value="1"/> + <param name="di_index_2" value="3"/> + <param name="di_vector" value="-0.9 -0.9 0"/> + <param name="interaction" value="dissipation"/> + <param name="dis_index" value="1"/> + <param name="dis_val" value="0.5"/> + <param name="average_axes" value="" /> + <param name="experiment_preset" value="custom" /> + <param name="field" value="1.5e-2 1.0e-2 1.0e-2"/> + <param name="field" value="0.01"/> + <param name="polarization_preset" value="custom"/> + <param name="polarization" value="1 0 0"/> + <param name="time" value="range(0,8.0,1000)"/> + <param name="time" value="range(0,1.0)"/> + <param name="orientation_preset" value="eulrange"/> + <param name="eul_n" value="10"/> + <output name="out_file" file="test_4.in" ftype="txt" compare="diff" /> + </test> + <test> + <param name="out_file_prefix" value="test_5"/> + <param name="spin_preset" value="mu"/> + <param name="interaction" value="dissipation"/> + <param name="dis_index" value="1"/> + <param name="dis_val" value="g"/> + <param name="experiment_preset" value="custom" /> + <param name="field" value="1.0/muon_gyr" /> + <param name="fitting" value="true"/> + <param name="var_name" value="g" /> + <param name="min_bound" value="0.0" /> + <param name="fitting_tolerance" value="1.0" /> + <output name="out_file" file="test_5.in" ftype="txt" compare="diff" /> + </test> + </tests> + <help><![CDATA[ + Tool to create input parameter file for Muspinsim. + + + This tool creates a structured text file with keywords and values which describe the system to model for Muspinsim. + See muspinsim docs for more information https://muon-spectroscopy-computational-project.github.io/muspinsim/input/. + + + Muspinsim allows expressions and special functions to be used when defining certain keywords. This tool also allows this. + Check the hint at the bottom of each input to see what, if any, special function or expressions can be used. + + + Default expressions include the use of the operators :code:`+ - * /` and :code:`^` for exponentiation. Expressions + should not contain whitespace. For example, use :code:`1+2` not :code:`1 + 2`. + + + Default constants include: + - :code:`pi`: ratio of a circle and its diameter + - :code:`e`: base of the natural logarithm + - :code:`deg`: conversion factor between radians and degrees, equivalent to 180/pi + - :code:`inf`: infinity + + Special constants include: + - :code:`muon_gyr`: gyromagnetic ratio of muon (135.5388 MHz/T) + - :code:`MHz`: :code:`1/(2*muon_gyr)` + + + Default functions include: + - :code:`sin(x)`: sine + - :code:`cos(x)`: cosine + - :code:`tan(x)`: tangent + - :code:`arcsin(x)`: inverse of the sine + - :code:`arccos(x)`: inverse of the cosine + - :code:`arctan(x)`: inverse of the tangent + - :code:`arctan2(y, x)`: inverse of the tangent taking two arguments as (sine, cosine) to resolve the quadrant + - :code:`exp(x)`: exponential with base e + - :code:`log(x)`: natural logarithm + - :code:`sqrt(x)`: square root + + Special functions include: + - :code:`range(x, y, z)`: get z equally spaced values between x and y + - :code:`zcw(n)`: Zaremba-Conroy-Wolfsberg helper function + - :code:`eulrange(n)`: helper function to create regular grid of n × n × n Euler angles with appropriate weights. + + + To enter vectors or matrices the following formats are accepted: + - :code:`[[1, 2, 3], [4, 5, 6], [7, 8, 9]]` + - :code:`1 2 3 4 5 6 7 8 9` + - :code:`[1 2 3] [4 5 6] [7 8 9]` + + + The fitting (function minimization) algorithms available are: + + + Nelder-Mead + - A direct search method. + - Starting with a 'simplex' of candidates, the algorithm will iteratively move the position of the worst candidate towards the optimum until all candidates converge (have values within a predefined tolerance level). + - Scipy default tolerance is :code:`1e-4` + + + L-BFGS + - Limited Memory Broyden–Fletcher–Goldfarb–Shanno algorithm. + - A second-order Quasi-Newton optimization algorithm + - Makes use of second-order derivative (Hessian Matrix) to converge on optimum. + - Scipy default tolerance is :code:`1e-5` + ]]></help> + <citations> + <citation type="bibtex"> + @article{nelder_mead_1965, + title={A Simplex Method for Function Minimization}, + volume={7}, + doi={10.1093/comjnl/7.4.308}, + number={4}, + journal={The Computer Journal}, + author={Nelder, J. A. and Mead, R.}, + year={1965}, + pages={308-313} + } + </citation> + <citation type="bibtex"> + @book{nocedal_wright_2006, + place={New York (NY)}, + title={Numerical Optimization}, + publisher={Springer}, + author={Nocedal, Jorge and Wright, Stephen J}, + year={2006} + } + </citation> + <citation type="bibtex"> + @TOOL_CITATION@ + </citation> + </citations> +</tool> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sample_fitting_data.dat Thu Aug 25 16:16:47 2022 +0000 @@ -0,0 +1,4 @@ +0 1 +2 3 +4 5 +6 7 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/test_1.in Thu Aug 25 16:16:47 2022 +0000 @@ -0,0 +1,20 @@ + +####################################################### +#Muspinsim Input File +#Generated using Muon Galaxy Tool Muspinsim_Input +####################################################### + +name + test_1 +spins + mu H +zeeman 2 + 2 0 0 +zeeman 1 + 1 0 0 +average_axes + orientation +x_axis + time +y_axis + asymmetry
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/test_2.in Thu Aug 25 16:16:47 2022 +0000 @@ -0,0 +1,26 @@ + +####################################################### +#Muspinsim Input File +#Generated using Muon Galaxy Tool Muspinsim_Input +####################################################### + +name + test_2 +spins + mu e +hyperfine 1 + 1 0 0 + sin(10) (5*2) 0 + 10*pi 5 cos(20) +average_axes + orientation +time + range(0,0.1) +temperature + 1.0 +x_axis + time +y_axis + asymmetry +field + 1.0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/test_3.in Thu Aug 25 16:16:47 2022 +0000 @@ -0,0 +1,27 @@ + +####################################################### +#Muspinsim Input File +#Generated using Muon Galaxy Tool Muspinsim_Input +####################################################### + +name + test_3 +spins + e mu H +hyperfine 3 + (300/2) 3 4*10 + 3 15*10 6-3+2 + 4 5 15 +hyperfine 2 + 580 5 10 + 5 580 9 + 10 9 580 +average_axes + polarization + temperature +orientation zyz + zcw(20) +field + range(1.8,2.6,100) +experiment + alc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/test_4.in Thu Aug 25 16:16:47 2022 +0000 @@ -0,0 +1,30 @@ + +####################################################### +#Muspinsim Input File +#Generated using Muon Galaxy Tool Muspinsim_Input +####################################################### + +name + test_4 +spins + mu F F +dissipation 1 + 0.5 +dipolar 1 3 + -0.9 -0.9 0 +dipolar 1 2 + 0.9 0.9 0 +orientation zyz + eulrange(10) +time + range(0,1.0) + range(0,8.0,1000) +x_axis + time +y_axis + asymmetry +field + 0.01 + 1.5e-2 1.0e-2 1.0e-2 +polarization + 1 0 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/test_5.in Thu Aug 25 16:16:47 2022 +0000 @@ -0,0 +1,28 @@ + +####################################################### +#Muspinsim Input File +#Generated using Muon Galaxy Tool Muspinsim_Input +####################################################### + +name + test_5 +spins + mu +dissipation 1 + g +average_axes + orientation +fitting_method + nelder-mead +fitting_variables + g 0 0.0 inf +fitting_tolerance + 1.0 +fitting_data + load("fitting_data.dat") +x_axis + time +y_axis + asymmetry +field + 1.0/muon_gyr