Skip to content

plot_solutions

Plot solution vectors from MFILEs to compare them.

This tool plots multiple solutions, or their differences, to allow comparisons of the solution vectors and objective function values. It allows normalisation to a given solution as well as plotting RMSEs relative to it.

If the MFILE is the result of a parameter scan, only the last point is plotted currently.

INITIAL_NORM_OPT_PARAM_VALUE_PATTERN = 'xcm' module-attribute

RANGE_NORM_OPT_PARAM_VALUE_PATTERN = 'nitvar' module-attribute

OPT_PARAM_VALUE_REGEX = '^itvar\\d{3}$' module-attribute

NORM_OPT_PARAM_NAME_REGEX = 'itvar\\d{3}_name' module-attribute

NORM_OBJF_PATTERN = 'objf' module-attribute

NORM_OBJF_VALUE = 'norm_objf' module-attribute

NORM_OBJF_NAME = 'objf_name' module-attribute

TAG_REGEX = 'tag$' module-attribute

TAG = 'tag' module-attribute

CON_VALUE_PATTERN = 'eq_con\\d{3}' module-attribute

CONSTRAINT_NUMS = {'eq_con001': 'EQ: beta, temperature, density', 'eq_con002': 'EQ: global plasma power balance', 'eq_con011': 'EQ: radial build', 'ineq_con030': 'UL: injection power', 'ineq_con015': 'LL: L-H threshold power', 'ineq_con016': 'LL: net electric power', 'ineq_con024': 'UL: beta', 'ineq_con025': 'UL: peak toroidal field', 'ineq_con026': 'UL: CS current density at EOF', 'ineq_con027': 'UL: CS current density at BOP', 'ineq_con033': 'UL: SCTF coil operating J', 'ineq_con034': 'UL: CSTF coil dump voltage', 'ineq_con035': 'UL: SCTF coil winding pack J', 'ineq_con036': 'LL: SCTF coil SC temp margin', 'ineq_con060': 'LL: CS SC temp margin', 'ineq_con062': 'LL: alpha:energy confinement times', 'ineq_con065': 'UL: stress on VV during TF quench', 'ineq_con072': 'UL: CS Tresca yield stress', 'ineq_con081': 'LL: central density > pedestal density', 'ineq_con068': 'UL: divertor protection limit', 'ineq_con031': 'UL: SCTF coil case stress', 'ineq_con032': 'UL: SCTF coil conduit stress', 'ineq_con005': 'UL: density', 'ineq_con008': 'UL: neutron wall load', 'ineq_con009': 'UL: fusion power', 'ineq_con013': 'LL: burn time'} module-attribute

RunMetadata dataclass

Metadata for a given Process run.

Define mfile for run and other information to identify it. Depending on what is being run/plotted, different fields can be undefined.

Source code in process/core/io/plot_solutions.py
75
76
77
78
79
80
81
82
83
84
@dataclass
class RunMetadata:
    """Metadata for a given Process run.

    Define mfile for run and other information to identify it. Depending on
    what is being run/plotted, different fields can be undefined.
    """

    mfile_path: Path
    tag: str

mfile_path instance-attribute

tag instance-attribute

plot_mfile_solutions(runs_metadata, plot_title, normalising_tag=None, rmse=False, normalisation_type='init')

Plot multiple solutions, optionally normalised by a given solution.

Parameters:

Name Type Description Default
runs_metadata Sequence[RunMetadata]

list of RunMetadata objects

required
plot_title str

title of plot

required
normalising_tag str

tag for solution to normalise with. If provided, normalise, otherwise don't, defaults to None

None
rmse bool

plot RMS errors relative to reference solution, defaults to False

False
normalisation_type str

opt param normalisation to use: one of ["init", "range", None], defaults to "init"

'init'

Returns:

Type Description
Tuple[Figure, DataFrame]

figure and dataframe of solutions

Source code in process/core/io/plot_solutions.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
def plot_mfile_solutions(
    runs_metadata: Sequence[RunMetadata],
    plot_title: str,
    normalising_tag: str | None = None,
    rmse: bool = False,
    normalisation_type: str | None = "init",
) -> tuple[mpl.figure.Figure, pd.DataFrame]:
    """Plot multiple solutions, optionally normalised by a given solution.

    Parameters
    ----------
    runs_metadata : Sequence[RunMetadata]
        list of RunMetadata objects
    plot_title : str
        title of plot
    normalising_tag : str, optional
        tag for solution to normalise with. If provided,
        normalise, otherwise don't, defaults to None
    rmse : bool, optional
        plot RMS errors relative to reference solution, defaults to False
    normalisation_type : str, optional
        opt param normalisation to use: one of ["init", "range", None], defaults to "init"

    Returns
    -------
    Tuple[mpl.figure.Figure, pd.DataFrame]
        figure and dataframe of solutions
    """
    if normalisation_type is not None and normalising_tag is not None:
        warn(
            "Double-normalising: using opt params normalised to each solution "
            "and normalising again to another solution. Are you sure?",
            stacklevel=1,
        )

    # Determine type of normalised opt params to plot (i.e. itvar, xcm or nitvar)
    if normalisation_type == "init":
        # Use values normalised to initial value for each solution: final/initial (xcm)
        opt_param_value_pattern = INITIAL_NORM_OPT_PARAM_VALUE_PATTERN
    elif normalisation_type == "range":
        # Use values normalised to allowed range of value (nitvar)
        opt_param_value_pattern = RANGE_NORM_OPT_PARAM_VALUE_PATTERN
    else:
        # No normalisation for each solution (itvar)
        opt_param_value_pattern = OPT_PARAM_VALUE_REGEX

    # Create dataframe from runs metadata: mfile data with a tag for each run
    results_df = _create_df_from_run_metadata(runs_metadata)

    # Filter for tag, optimisation parameters and objective function
    filtered_results_df = _filter_vars_of_interest(
        results_df,
        opt_param_value_pattern=opt_param_value_pattern,
        extra_var_names=["minmax"],
    )

    if normalising_tag is not None:
        # Calculate the normalised diffs relative to the tagged solution
        plot_results_df = _normalise_diffs(
            filtered_results_df,
            opt_param_value_pattern=opt_param_value_pattern,
            normalising_tag=normalising_tag,
        )
    else:
        # Don't perform any processing of optimisation parameters
        plot_results_df = filtered_results_df

    if rmse:
        if normalising_tag is None:
            raise ValueError(
                "RMSE plot requires normalising_tag to be specified: which "
                "solution are the errors relative to?"
            )

        # Calcualte RMS errors relative to normalising tag solution
        rmse_df = _rms_errors(
            results_df=results_df,
            opt_param_value_pattern=opt_param_value_pattern,
            normalising_tag=normalising_tag,
        )
    else:
        # Don't plot RMS errors
        rmse_df = None

    fig = _plot_solutions(
        plot_results_df,
        opt_param_value_pattern=opt_param_value_pattern,
        plot_title=plot_title,
        rmse_df=rmse_df,
        normalising_tag=normalising_tag,
        normalisation_type=normalisation_type,
    )

    # Return fig for optional further customisation
    # fig as varying numbers of axes depending on plot type
    return fig, filtered_results_df

plot_mfile_solutions_constraints(runs_metadata, title)

Plot constraint values in mfiles.

Parameters:

Name Type Description Default
runs_metadata Sequence[RunMetadata]

list of RunMetadata objects

required
title str

plot title

required

Returns:

Type Description
tuple[Figure, DataFrame]

figure and dataframe of solutions

Source code in process/core/io/plot_solutions.py
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
def plot_mfile_solutions_constraints(
    runs_metadata: Sequence[RunMetadata], title: str
) -> tuple[mpl.figure.Figure, pd.DataFrame]:
    """Plot constraint values in mfiles.

    Parameters
    ----------
    runs_metadata:
        list of RunMetadata objects
    title:
        plot title

    Returns
    -------
    :
        figure and dataframe of solutions
    """
    # Create dataframe from runs metadata: mfile data with a tag for each run
    results_df = _create_df_from_run_metadata(runs_metadata)

    # Filter for tag and constraint values
    filtered_results_df = _filter_vars_of_interest(results_df, constraints=True)

    fig = _plot_solutions_constraints(df=filtered_results_df, title=title)
    return fig, filtered_results_df