Skip to content

Commit

Permalink
Condense repetitive dashboard code (#780)
Browse files Browse the repository at this point in the history
* Centralize vselect and vtextfields

* Centralize documentation code

* Centralize section header code

* Fix multigrid settings

* Centralize dialog settings code for lattice config and space charge

* Add staticmethods

* Centralize some more space charge functions

* Reduce code for calling toolbars

* Remove redundant error_message state inits

* Create initialize_states() and remove redundant state initialization

Future commit needs to create init_states by section rather than at once call

* Remove state inits for dialogs

Dialogs defaults will always be false, not necessary to expicitly state it

* Correctly condense refresh input functionality into input_section_header()

* Provide default v_model_name if not given

* rename selected_distribution and selected_distribution_type to distribution and distribution_type

This was already changed from selectedDistribution and selectedDistributionType to selected_distribution and distribution_type and this is the second variable name change

* Simplify inputMain.py

* Centralize shared imports in Input/__init__.py

* Simplify csrConfiguration

* Update more of distributionMain.py

variable name change relocte logic

* Simplify duplicated lattice config code

* Remove print statement
  • Loading branch information
proy30 authored Jan 10, 2025
1 parent f68e03c commit 8ef479d
Show file tree
Hide file tree
Showing 13 changed files with 385 additions and 649 deletions.
14 changes: 14 additions & 0 deletions src/python/impactx/dashboard/Input/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from trame.widgets import vuetify as vuetify

from ..trame_setup import setup_server
from .defaults import DashboardDefaults
from .generalFunctions import generalFunctions
from .trameFunctions import TrameFunctions

__all__ = [
"vuetify",
"DashboardDefaults",
"TrameFunctions",
"generalFunctions",
"setup_server",
]
56 changes: 5 additions & 51 deletions src/python/impactx/dashboard/Input/csrConfiguration/csrMain.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,7 @@
from trame.widgets import vuetify

from ...Input.trameFunctions import TrameFunctions
from ...trame_setup import setup_server
from ..generalFunctions import generalFunctions
from .. import TrameFunctions, setup_server, vuetify

server, state, ctrl = setup_server()

# -----------------------------------------------------------------------------
# Default State Variables
# -----------------------------------------------------------------------------

state.csr_bins = generalFunctions.get_default("csr_bins", "default_values")
state.csr_bins_error_message = ""

# -----------------------------------------------------------------------------
#
# -----------------------------------------------------------------------------


@state.change("csr_bins")
def on_csr_bins_change(csr_bins, **kwargs):
error_message = generalFunctions.validate_against(csr_bins, "int", ["positive"])
state.csr_bins_error_message = error_message
generalFunctions.update_simulation_validation_status()


# -----------------------------------------------------------------------------
# UI
# -----------------------------------------------------------------------------


class csrConfiguration:
@staticmethod
Expand All @@ -38,35 +11,16 @@ def card():
"""

with vuetify.VCard(v_show="csr", style="width: 170px;"):
with vuetify.VCardTitle("CSR"):
vuetify.VSpacer()
TrameFunctions.create_refresh_button(
lambda: generalFunctions.reset_inputs("csr")
)
vuetify.VIcon(
"mdi-information",
classes="ml-2",
click=lambda: generalFunctions.documentation("CSR"),
style="color: #00313C;",
)
vuetify.VDivider()
TrameFunctions.input_section_header("CSR")
with vuetify.VCardText():
with vuetify.VRow(classes="my-0"):
with vuetify.VCol(classes="py-0"):
vuetify.VSelect(
TrameFunctions.select(
label="Particle Shape",
v_model=("particle_shape",),
items=([1, 2, 3],),
dense=True,
)
with vuetify.VRow(classes="my-0"):
with vuetify.VCol(classes="py-0"):
vuetify.VTextField(
TrameFunctions.text_field(
label="CSR Bins",
v_model=("csr_bins",),
error_messages=("csr_bins_error_message",),
type="number",
dense=True,
step=generalFunctions.get_default("csr_bins", "steps"),
__properties=["step"],
input=(ctrl.input_change, "['csr_bins']"),
)
28 changes: 22 additions & 6 deletions src/python/impactx/dashboard/Input/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ class DashboardDefaults:
"mass_MeV": 0.51099895,
"npart": 1000,
"kin_energy": 2e3,
"kin_energy_MeV": 2e3,
"kin_energy_unit": "MeV",
"bunch_charge_C": 1e-9,
}

DISTRIBUTION = {
"selected_distribution": "Waterbag",
"selected_distribution_type": "Twiss",
DISTRIBUTION_PARAMETERS = {
"distribution": "Waterbag",
"distribution_type": "Twiss",
}

LATTICE = {
LATTICE_CONFIGURATION = {
"selected_lattice_list": [],
"selected_lattice": None,
}
Expand Down Expand Up @@ -70,13 +71,28 @@ class DashboardDefaults:
DEFAULT_VALUES = {
**SELECTION,
**INPUT_PARAMETERS,
**DISTRIBUTION,
**LATTICE,
**DISTRIBUTION_PARAMETERS,
**LATTICE_CONFIGURATION,
**SPACE_CHARGE,
**CSR,
**LISTS,
}

TYPES = {
"npart": "int",
"kin_energy": "float",
"bunch_charge_C": "float",
"mass_MeV": "float",
"charge_qe": "int",
"csr_bins": "int",
}

VALIDATION_CONDITION = {
"charge_qe": ["non_zero"],
"mass_MeV": ["positive"],
"csr_bins": ["positive"],
}

# If a parameter is not included in the dictionary, default step amount is 1.
STEPS = {
"mass_MeV": 0.1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@
import inspect

from distribution_input_helpers import twiss
from trame.widgets import vuetify

from impactx import distribution

from ...Input.trameFunctions import TrameFunctions
from ...trame_setup import setup_server
from ..generalFunctions import generalFunctions
from .. import TrameFunctions, generalFunctions, setup_server, vuetify
from .distributionFunctions import DistributionFunctions

server, state, ctrl = setup_server()
Expand All @@ -24,39 +21,28 @@
# Helpful
# -----------------------------------------------------------------------------

DISTRIBUTIONS_MODULE_NAME = distribution

state.listOfDistributions = generalFunctions.select_classes(DISTRIBUTIONS_MODULE_NAME)
state.listOfDistributionsAndParametersAndDefault = (
generalFunctions.class_parameters_with_defaults(DISTRIBUTIONS_MODULE_NAME)
DISTRIBUTION_MODULE_NAME = distribution
DISTRIBUTION_LIST = generalFunctions.select_classes(DISTRIBUTION_MODULE_NAME)
DISTRIBUTION_PARAMETERS_AND_DEFAULTS = generalFunctions.class_parameters_with_defaults(
DISTRIBUTION_MODULE_NAME
)

# -----------------------------------------------------------------------------
# Defaults
# -----------------------------------------------------------------------------

state.selected_distribution = generalFunctions.get_default(
"selected_distribution", "default_values"
)
state.selected_distribution_type = generalFunctions.get_default(
"selected_distribution_type", "default_values"
)
state.selected_distribution_parameters = []
state.distributionTypeDisabled = False
state.distribution_type_disable = False

# -----------------------------------------------------------------------------
# Main Functions
# -----------------------------------------------------------------------------


def populate_distribution_parameters(selected_distribution):
def populate_distribution_parameters():
"""
Populates distribution parameters based on the selected distribution.
:param selected_distribution (str): The name of the selected distribution
whose parameters need to be populated.
"""

if state.selected_distribution_type == "Twiss":
if state.distribution_type == "Twiss":
sig = inspect.signature(twiss)
state.selected_distribution_parameters = [
{
Expand All @@ -77,10 +63,8 @@ def populate_distribution_parameters(selected_distribution):
]

else: # when type == 'Quadratic Form'
selected_distribution_parameters = (
state.listOfDistributionsAndParametersAndDefault.get(
selected_distribution, []
)
selected_distribution_parameters = DISTRIBUTION_PARAMETERS_AND_DEFAULTS.get(
state.distribution, []
)

state.selected_distribution_parameters = [
Expand All @@ -103,26 +87,6 @@ def populate_distribution_parameters(selected_distribution):
return state.selected_distribution_parameters


def update_distribution_parameters(
parameterName, parameterValue, parameterErrorMessage
):
"""
Updates the value of a distribution parameter and its error message.
:param parameterName (str): The name of the parameter to update.
:param parameterValue: The new value for the parameter.
:param parameterErrorMessage: The error message related to the parameter's value.
"""

for param in state.selected_distribution_parameters:
if param["parameter_name"] == parameterName:
param["parameter_default_value"] = parameterValue
param["parameter_error_message"] = parameterErrorMessage

generalFunctions.update_simulation_validation_status()
state.dirty("selected_distribution_parameters")


# -----------------------------------------------------------------------------
# Write to file functions
# -----------------------------------------------------------------------------
Expand All @@ -134,10 +98,10 @@ def distribution_parameters():
initialized with the appropriate parameters provided by the user.
"""

distribution_name = state.selected_distribution
distribution_name = state.distribution
parameters = DistributionFunctions.convert_distribution_parameters_to_valid_type()

if state.selected_distribution_type == "Twiss":
if state.distribution_type == "Twiss":
twiss_params = twiss(**parameters)
distr = getattr(distribution, distribution_name)(**twiss_params)
else:
Expand All @@ -151,28 +115,34 @@ def distribution_parameters():
# -----------------------------------------------------------------------------


@state.change("selected_distribution")
def on_distribution_name_change(selected_distribution, **kwargs):
if selected_distribution == "Thermal":
state.selected_distribution_type = "Quadratic Form"
state.distributionTypeDisabled = True
state.dirty("selected_distribution_type")
@state.change("distribution")
def on_distribution_name_change(distribution, **kwargs):
if distribution == "Thermal":
state.distribution_type = "Quadratic Form"
state.distribution_type_disable = True
state.dirty("distribution_type")
else:
state.distributionTypeDisabled = False
populate_distribution_parameters(selected_distribution)
state.distribution_type_disable = False
populate_distribution_parameters()


@state.change("selected_distribution_type")
@state.change("distribution_type")
def on_distribution_type_change(**kwargs):
populate_distribution_parameters(state.selected_distribution)
populate_distribution_parameters()


@ctrl.add("updateDistributionParameters")
def on_distribution_parameter_change(parameter_name, parameter_value, parameter_type):
parameter_value, input_type = generalFunctions.determine_input_type(parameter_value)
error_message = generalFunctions.validate_against(parameter_value, parameter_type)

update_distribution_parameters(parameter_name, parameter_value, error_message)
for param in state.selected_distribution_parameters:
if param["parameter_name"] == parameter_name:
param["parameter_default_value"] = parameter_value
param["parameter_error_message"] = error_message

generalFunctions.update_simulation_validation_status()
state.dirty("selected_distribution_parameters")


# -----------------------------------------------------------------------------
Expand All @@ -192,47 +162,29 @@ def card():
"""

with vuetify.VCard(style="width: 340px; height: 300px"):
with vuetify.VCardTitle("Distribution Parameters"):
vuetify.VSpacer()
TrameFunctions.create_refresh_button(
lambda: generalFunctions.reset_inputs("distribution")
)
vuetify.VIcon(
"mdi-information",
style="color: #00313C;",
click=lambda: generalFunctions.documentation("BeamDistributions"),
)
vuetify.VDivider()
TrameFunctions.input_section_header("Distribution Parameters")
with vuetify.VCardText():
with vuetify.VRow():
with vuetify.VCol(cols=6):
vuetify.VCombobox(
TrameFunctions.select(
label="Select Distribution",
v_model=("selected_distribution",),
items=("listOfDistributions",),
dense=True,
v_model_name="distribution",
items=(DISTRIBUTION_LIST,),
)
with vuetify.VCol(cols=6):
vuetify.VSelect(
v_model=("selected_distribution_type",),
TrameFunctions.select(
label="Type",
items=(
generalFunctions.get_default(
"distribution_type_list", "default_values"
),
),
dense=True,
disabled=("distributionTypeDisabled",),
v_model_name="distribution_type",
disabled=("distribution_type_disable",),
)
with vuetify.VRow(classes="my-2"):
for i in range(3):
with vuetify.VCol(cols=4, classes="py-0"):
with vuetify.VRow(
v_for="(parameter, index) in selected_distribution_parameters"
v_for="(parameter, index) in selected_distribution_parameters",
v_if=f"index % 3 == {i}",
):
with vuetify.VCol(
v_if=f"index % 3 == {i}", classes="py-1"
):
with vuetify.VCol(classes="py-1"):
vuetify.VTextField(
label=("parameter.parameter_name",),
v_model=("parameter.parameter_default_value",),
Expand Down
Loading

0 comments on commit 8ef479d

Please sign in to comment.