From d604be2d8111da4aaab944041fef63c0fa43185e Mon Sep 17 00:00:00 2001 From: Parthib Roy Date: Sat, 19 Oct 2024 13:06:37 -0700 Subject: [PATCH 1/7] Updated UI for distributions Twiss is now default, 'Native' changed to 'Quadratic Form' and placed as secondary option --- .../Input/distributionParameters/distributionMain.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py index b57e16fe7..e319b8e94 100644 --- a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py +++ b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py @@ -31,7 +31,7 @@ # ----------------------------------------------------------------------------- state.selectedDistribution = "Waterbag" -state.selectedDistributionType = "Native" +state.selectedDistributionType = "Twiss" state.selectedDistributionParameters = [] # ----------------------------------------------------------------------------- @@ -172,21 +172,19 @@ def card(): vuetify.VDivider() with vuetify.VCardText(): with vuetify.VRow(): - with vuetify.VCol(cols=8): + with vuetify.VCol(cols=6): vuetify.VCombobox( label="Select Distribution", v_model=("selectedDistribution",), items=("listOfDistributions",), dense=True, ) - with vuetify.VCol(cols=4): + with vuetify.VCol(cols=6): vuetify.VSelect( v_model=("selectedDistributionType",), label="Type", - items=(["Native", "Twiss"],), - # change=(ctrl.kin_energy_unit_change, "[$event]"), + items=(["Twiss", "Quadratic Form"],), dense=True, - disabled=True, ) with vuetify.VRow(classes="my-2"): for i in range(3): From 337197c8736adb12b56205212b438dbd4fb8c243 Mon Sep 17 00:00:00 2001 From: Parthib Roy Date: Sat, 19 Oct 2024 13:42:32 -0700 Subject: [PATCH 2/7] Refactor distribution helper function Helper function moved to distributionFuntions.py, and simplified code structure. no functionality change --- .../distributionFunctions.py | 31 +++++++++++++++++++ .../distributionMain.py | 21 ++----------- .../dashboard/Toolbar/exportTemplate.py | 4 +-- 3 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 src/python/impactx/dashboard/Input/distributionParameters/distributionFunctions.py diff --git a/src/python/impactx/dashboard/Input/distributionParameters/distributionFunctions.py b/src/python/impactx/dashboard/Input/distributionParameters/distributionFunctions.py new file mode 100644 index 000000000..abeff3bce --- /dev/null +++ b/src/python/impactx/dashboard/Input/distributionParameters/distributionFunctions.py @@ -0,0 +1,31 @@ +from ...trame_setup import setup_server + +server, state, ctrl = setup_server() + +# ----------------------------------------------------------------------------- +# Functions +# ----------------------------------------------------------------------------- + + +class DistributionFunctions: + """ + Helper functions for the + User-Input section for beam properties. + """ + + @staticmethod + def convert_distribution_parameters_to_valid_type(): + """ + Helper function to check if user input is valid. + :return: A dictionary with parameter names as keys and their validated values. + """ + + parameter_input = { + param["parameter_name"]: float(param["parameter_default_value"]) + if param_is_valid + else 0.0 + for param in state.selectedDistributionParameters + if (param_is_valid := param["parameter_error_message"] == []) + } + + return parameter_input diff --git a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py index e319b8e94..c96b87e5e 100644 --- a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py +++ b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py @@ -12,6 +12,7 @@ from ...trame_setup import setup_server from ..generalFunctions import generalFunctions +from .distributionFunctions import DistributionFunctions server, state, ctrl = setup_server() @@ -91,24 +92,6 @@ def update_distribution_parameters( # ----------------------------------------------------------------------------- -def parameter_input_checker(): - """ - Helper function to check if user input is valid. - :return: A dictionary with parameter names as keys and their validated values. - """ - - parameter_input = {} - for param in state.selectedDistributionParameters: - if param["parameter_error_message"] == []: - parameter_input[param["parameter_name"]] = float( - param["parameter_default_value"] - ) - else: - parameter_input[param["parameter_name"]] = 0.0 - - return parameter_input - - def distribution_parameters(): """ Writes user input for distribution parameters in suitable format for simulation code. @@ -116,7 +99,7 @@ def distribution_parameters(): """ distribution_name = state.selectedDistribution - parameters = parameter_input_checker() + parameters = DistributionFunctions.convert_distribution_parameters_to_valid_type() distr = getattr(distribution, distribution_name)(**parameters) return distr diff --git a/src/python/impactx/dashboard/Toolbar/exportTemplate.py b/src/python/impactx/dashboard/Toolbar/exportTemplate.py index 157c019e2..8fe30492c 100644 --- a/src/python/impactx/dashboard/Toolbar/exportTemplate.py +++ b/src/python/impactx/dashboard/Toolbar/exportTemplate.py @@ -1,4 +1,4 @@ -from ..Input.distributionParameters.distributionMain import parameter_input_checker +from ..Input.distributionParameters.distributionFunctions import DistributionFunctions from ..Input.latticeConfiguration.latticeMain import parameter_input_checker_for_lattice from ..trame_setup import setup_server @@ -15,7 +15,7 @@ def build_distribution_list(): as a string for exporting purposes. """ distribution_name = state.selectedDistribution - parameters = parameter_input_checker() + parameters = DistributionFunctions.convert_distribution_parameters_to_valid_type() distribution_parameters = ",\n ".join( f"{key}={value}" for key, value in parameters.items() From 5984f7700a0486703bdb6c41400f4ae9e72c7c7e Mon Sep 17 00:00:00 2001 From: Parthib Roy Date: Sat, 19 Oct 2024 14:04:39 -0700 Subject: [PATCH 3/7] Updated docstring/comments --- .../Input/distributionParameters/distributionFunctions.py | 7 ++++--- .../Input/distributionParameters/distributionMain.py | 6 +++--- .../dashboard/Input/inputParameters/inputFunctions.py | 3 +-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/python/impactx/dashboard/Input/distributionParameters/distributionFunctions.py b/src/python/impactx/dashboard/Input/distributionParameters/distributionFunctions.py index abeff3bce..7565c2c5c 100644 --- a/src/python/impactx/dashboard/Input/distributionParameters/distributionFunctions.py +++ b/src/python/impactx/dashboard/Input/distributionParameters/distributionFunctions.py @@ -9,14 +9,15 @@ class DistributionFunctions: """ - Helper functions for the - User-Input section for beam properties. + Helper functions for the distribution parameters. """ @staticmethod def convert_distribution_parameters_to_valid_type(): """ - Helper function to check if user input is valid. + Helper function to convert user-inputted distribution parameters + from string type to float type. + :return: A dictionary with parameter names as keys and their validated values. """ diff --git a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py index c96b87e5e..cf3fa2997 100644 --- a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py +++ b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py @@ -28,7 +28,7 @@ ) # ----------------------------------------------------------------------------- -# Default +# Defaults # ----------------------------------------------------------------------------- state.selectedDistribution = "Waterbag" @@ -94,8 +94,8 @@ def update_distribution_parameters( def distribution_parameters(): """ - Writes user input for distribution parameters in suitable format for simulation code. - :return: An instance of the selected distribution class, initialized with user-provided parameters. + :return: An instance of the selected distribution class, + initialized with the appropriate parameters provided by the user. """ distribution_name = state.selectedDistribution diff --git a/src/python/impactx/dashboard/Input/inputParameters/inputFunctions.py b/src/python/impactx/dashboard/Input/inputParameters/inputFunctions.py index 0624ef7b0..30bfdfdfa 100644 --- a/src/python/impactx/dashboard/Input/inputParameters/inputFunctions.py +++ b/src/python/impactx/dashboard/Input/inputParameters/inputFunctions.py @@ -26,8 +26,7 @@ class InputFunctions: """ - Helper functions for the - User-Input section for beam properties. + Helper functions for the beam properties. """ @staticmethod From fa140fde880a0b1f45ed4d703a6fef3fa757b692 Mon Sep 17 00:00:00 2001 From: Parthib Roy Date: Sat, 19 Oct 2024 16:03:30 -0700 Subject: [PATCH 4/7] Updated export_template to handle twiss parameters --- .../dashboard/Toolbar/exportTemplate.py | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/python/impactx/dashboard/Toolbar/exportTemplate.py b/src/python/impactx/dashboard/Toolbar/exportTemplate.py index 8fe30492c..4effd2de6 100644 --- a/src/python/impactx/dashboard/Toolbar/exportTemplate.py +++ b/src/python/impactx/dashboard/Toolbar/exportTemplate.py @@ -17,13 +17,25 @@ def build_distribution_list(): distribution_name = state.selectedDistribution parameters = DistributionFunctions.convert_distribution_parameters_to_valid_type() - distribution_parameters = ",\n ".join( - f"{key}={value}" for key, value in parameters.items() + indentation = " " * (8 if state.selectedDistributionType == "Twiss" else 4) + distribution_parameters = ",\n".join( + f"{indentation}{key}={value}" for key, value in parameters.items() ) - return ( - f"distr = distribution.{distribution_name}(\n {distribution_parameters},\n)" - ) + if state.selectedDistributionType == "Twiss": + return ( + f"distr = distribution.{distribution_name}(\n" + f" **twiss(\n" + f"{distribution_parameters},\n" + f" )\n" + f")" + ) + else: + return ( + f"distr = distribution.{distribution_name}(\n" + f"{distribution_parameters},\n" + f")" + ) def build_lattice_list(): @@ -56,7 +68,7 @@ def input_file(): dashboard user inputs into a python script. """ script = f""" -from impactx import ImpactX, distribution, elements +from impactx import ImpactX, distribution, elements, twiss sim = ImpactX() From a4177f9e7be3ed18278f931884f823ce82f608a9 Mon Sep 17 00:00:00 2001 From: Parthib Roy Date: Sat, 19 Oct 2024 16:20:31 -0700 Subject: [PATCH 5/7] Add twiss parameter functionality for distribution --- .../distributionMain.py | 67 +++++++++++++------ 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py index cf3fa2997..09a6a63cb 100644 --- a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py +++ b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py @@ -6,6 +6,9 @@ License: BSD-3-Clause-LBNL """ +import inspect + +from distribution_input_helpers import twiss from trame.widgets import vuetify from impactx import distribution @@ -47,24 +50,43 @@ def populate_distribution_parameters(selectedDistribution): whos parameters need to be populated. """ - selectedDistributionParameters = ( - state.listOfDistributionsAndParametersAndDefault.get(selectedDistribution, []) - ) - - state.selectedDistributionParameters = [ - { - "parameter_name": parameter[0], - "parameter_default_value": parameter[1], - "parameter_type": parameter[2], - "parameter_error_message": generalFunctions.validate_against( - parameter[1], parameter[2] - ), - } - for parameter in selectedDistributionParameters - ] - - generalFunctions.update_simulation_validation_status() - return selectedDistributionParameters + if state.selectedDistributionType == "Twiss": + sig = inspect.signature(twiss) + state.selectedDistributionParameters = [ + { + "parameter_name": param.name, + "parameter_default_value": param.default + if param.default != param.empty + else None, + "parameter_type": "float", # Harcoding Twiss to 'float' type. + "parameter_error_message": generalFunctions.validate_against( + param.default if param.default != param.empty else None, "float" + ), + } + for param in sig.parameters.values() + ] + + else: # when type == 'Quadratic Form' + selectedDistributionParameters = ( + state.listOfDistributionsAndParametersAndDefault.get( + selectedDistribution, [] + ) + ) + + state.selectedDistributionParameters = [ + { + "parameter_name": parameter[0], + "parameter_default_value": parameter[1], + "parameter_type": parameter[2], + "parameter_error_message": generalFunctions.validate_against( + parameter[1], parameter[2] + ), + } + for parameter in selectedDistributionParameters + ] + + generalFunctions.update_simulation_validation_status() + return selectedDistributionParameters def update_distribution_parameters( @@ -95,13 +117,18 @@ def update_distribution_parameters( def distribution_parameters(): """ :return: An instance of the selected distribution class, - initialized with the appropriate parameters provided by the user. + initialized with the appropriate parameters provided by the user. """ distribution_name = state.selectedDistribution parameters = DistributionFunctions.convert_distribution_parameters_to_valid_type() - distr = getattr(distribution, distribution_name)(**parameters) + if state.selectedDistributionType == "Twiss": + twiss_params = twiss(**parameters) + distr = getattr(distribution, distribution_name)(**twiss_params) + else: + distr = getattr(distribution, distribution_name)(**parameters) + return distr From 7d8151f1f355012f568ce461b016d6f2af979458 Mon Sep 17 00:00:00 2001 From: Parthib Roy Date: Sat, 19 Oct 2024 19:47:25 -0700 Subject: [PATCH 6/7] Updated functionality to correctly display 'Thermal' distribution parameters Thermal is set to have a single set of parameters - 'k', 'kT', 'kT_halo', 'normali ze', 'normalize_halo', halo' --- .../Input/distributionParameters/distributionMain.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py index 09a6a63cb..0da8f63b2 100644 --- a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py +++ b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py @@ -37,6 +37,7 @@ state.selectedDistribution = "Waterbag" state.selectedDistributionType = "Twiss" state.selectedDistributionParameters = [] +state.distributionTypeDisabled = False # ----------------------------------------------------------------------------- # Main Functions @@ -47,7 +48,7 @@ def populate_distribution_parameters(selectedDistribution): """ Populates distribution parameters based on the selected distribution. :param selectedDistribution (str): The name of the selected distribution - whos parameters need to be populated. + whose parameters need to be populated. """ if state.selectedDistributionType == "Twiss": @@ -58,7 +59,7 @@ def populate_distribution_parameters(selectedDistribution): "parameter_default_value": param.default if param.default != param.empty else None, - "parameter_type": "float", # Harcoding Twiss to 'float' type. + "parameter_type": "float", # Hardcoding Twiss to 'float' type. "parameter_error_message": generalFunctions.validate_against( param.default if param.default != param.empty else None, "float" ), @@ -139,6 +140,12 @@ def distribution_parameters(): @state.change("selectedDistribution") def on_distribution_name_change(selectedDistribution, **kwargs): + if selectedDistribution == "Thermal": + state.selectedDistributionType = "Quadratic Form" + state.distributionTypeDisabled = True + state.dirty("selectedDistributionType") + else: + state.distributionTypeDisabled = False populate_distribution_parameters(selectedDistribution) @@ -195,6 +202,7 @@ def card(): label="Type", items=(["Twiss", "Quadratic Form"],), dense=True, + disabled=("distributionTypeDisabled",), ) with vuetify.VRow(classes="my-2"): for i in range(3): From 59543e8cc936aaeef6a294eaf4ce483cca72e5de Mon Sep 17 00:00:00 2001 From: Parthib Roy Date: Fri, 25 Oct 2024 15:44:15 -0700 Subject: [PATCH 7/7] Add units for beta/emitt --- .../Input/distributionParameters/distributionMain.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py index 0da8f63b2..a1f9d6c2b 100644 --- a/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py +++ b/src/python/impactx/dashboard/Input/distributionParameters/distributionMain.py @@ -63,6 +63,9 @@ def populate_distribution_parameters(selectedDistribution): "parameter_error_message": generalFunctions.validate_against( param.default if param.default != param.empty else None, "float" ), + "parameter_units": "m" + if "beta" in param.name or "emitt" in param.name + else "", } for param in sig.parameters.values() ] @@ -82,6 +85,9 @@ def populate_distribution_parameters(selectedDistribution): "parameter_error_message": generalFunctions.validate_against( parameter[1], parameter[2] ), + "parameter_units": "m" + if "beta" in parameter[0] or "emitt" in parameter[0] + else "", } for parameter in selectedDistributionParameters ] @@ -216,6 +222,7 @@ def card(): vuetify.VTextField( label=("parameter.parameter_name",), v_model=("parameter.parameter_default_value",), + suffix=("parameter.parameter_units",), change=( ctrl.updateDistributionParameters, "[parameter.parameter_name, $event, parameter.parameter_type]",