diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index 8bc170ea5..0c16c0c31 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -20,7 +20,7 @@ __all__ = ['coords_transform', 'get_nIne1e2', 'get_X12fromflat', 'compute_RaysCones', - 'create_config', + 'get_available_config', 'create_config', 'create_CamLOS1D', 'create_CamLOS2D'] @@ -643,8 +643,16 @@ def _compute_CamLOS2D_pinhole(P=None, F=0.1, D12=0.1, N12=100, _ExpJET = 'JET' _ExpITER = 'ITER' _ExpNSTX = 'NSTX' +# Default config +_DEFCONFIG = 'ITER' + +_URL_TUTO = ('https://tofuproject.github.io/tofu/auto_examples/tutorials/' + + 'tuto_plot_create_geometry.html') # Dictionnary of unique config names +# For each config, indicates which structural elements it comprises +# Elements are sorted by class (Ves, PFC...) +# For each element, a unique txt file containing the geometry will be loaded _DCONFIG = {'WEST-V1': {'Exp': _ExpWest, 'Ves': ['V1']}, 'ITER-V1': {'Exp': _ExpITER, @@ -680,28 +688,78 @@ def _compute_CamLOS2D_pinhole(P=None, F=0.1, D12=0.1, N12=100, 'Ves': ['V0']} } -# Each config can be called by various names (for benchmark and -# retro-compatibility), this table stores the available names for each unique -# config in _DCONFIG -_DCONFIG_TABLE = {'ITER': 'ITER-V2', - 'JET': 'JET-V0', - 'WEST': 'WEST-V4', - 'A1': 'WEST-V1', - 'A2': 'ITER-V1', - 'A3': 'WEST-Sep', - 'B1': 'WEST-V2', - 'B2': 'WEST-V3', - 'B3': 'WEST-V4', - 'B4': 'ITER-V2', - 'NSTX': 'NSTX-V0'} +# Each config can be called by various names / shortcuts (for benchmark and +# retro-compatibility), this table stores, for each shortcut, +# the associated unique name it refers to +_DCONFIG_SHORTCUTS = {'ITER': 'ITER-V2', + 'JET': 'JET-V0', + 'WEST': 'WEST-V4', + 'A1': 'WEST-V1', + 'A2': 'ITER-V1', + 'A3': 'WEST-Sep', + 'B1': 'WEST-V2', + 'B2': 'WEST-V3', + 'B3': 'WEST-V4', + 'B4': 'ITER-V2', + 'NSTX': 'NSTX-V0'} + + +def _get_listconfig(dconfig=_DCONFIG, dconfig_shortcuts=_DCONFIG_SHORTCUTS, + returnas=str): + """ Hidden function generating the config names table as a str or dict """ + assert returnas in [dict, str] + dc = {k0: [k0] + sorted([k1 for k1, v1 in dconfig_shortcuts.items() + if v1 == k0]) + for k0 in sorted(dconfig.keys())} + if returnas is dict: + return dc + else: + l0 = np.max([len(k0) for k0 in dc.keys()] + [len('unique names')]) + l1 = np.max([len(str(v0)) for v0 in dc.values()] + [len('shortcuts')]) + msg = ("\n\t" + "unique names".ljust(l0) + "\tshortcuts" + + "\n\t" + "-"*l0 + " \t" + "-"*l1 + + "\n\t- " + + "\n\t- ".join(["{}\t{}".format(k0.ljust(l0), v0) + for k0, v0 in dc.items()])) + return msg -# Default config -_DEFCONFIG = 'ITER' + +def get_available_config(dconfig=_DCONFIG, + dconfig_shortcuts=_DCONFIG_SHORTCUTS, + verb=True, returnas=False): + """ Print a table showing all pre-defined config + + Each pre-defined config in tofu can be called by its unique name or + by a series of shortcuts / alterantive names refereing to the same unique + name. this feature is useful for retro-compatibility and for making sure a + standard name always refers to the latest (most detailed) available version + of the geometry. + + Can also return the table as str + + No input arg needed: + >>> import tofu as tf + >>> tf.geom.utils.get_available_config() + + """ + msg = ("A config is the geometry of a tokamak\n" + + "You can define your own" + + ", see online tutorial at:\n\t{}\n".format(_URL_TUTO) + + "tofu also also provides some pre-defined config ready to load\n" + + "They are available via their name or via shortcuts\n" + + _get_listconfig(dconfig=dconfig, + dconfig_shortcuts=dconfig_shortcuts) + + "\n\n => to get a pre-defined config, call for example:\n" + + "\tconfig = tf.geom.utils.create_config('ITER')") + if verb is True: + print(msg) + if returnas in [None, True, str]: + return msg def _create_config_testcase(config=None, returnas='object', path=_path_testcases, dconfig=_DCONFIG, - dconfig_table=_DCONFIG_TABLE): + dconfig_shortcuts=_DCONFIG_SHORTCUTS): """ Load the desired test case configuration Choose from one of the reference preset configurations: @@ -719,16 +777,14 @@ def _create_config_testcase(config=None, returnas='object', if config in dconfig.keys(): pass - elif config in dconfig_table.keys(): + elif config in dconfig_shortcuts.keys(): # Get corresponding config - config = dconfig_table[config] + config = dconfig_shortcuts[config] else: - msg = ("The provided config name is not valid:\n" - + "Please choose among either:\n" - + "\t - unique keys: {}\n".format(list(dconfig.keys())) - + "\t - shortcuts : {}\n\n".format(list(dconfig_table.keys())) - + " => you provided: case = {}\n".format(config)) + msg = ("\nThe provided config name is not valid.\n" + + get_available_config(verb=False, returnas=str) + + "\n\n => you provided: {}\n".format(config)) raise Exception(msg) # Get file names for config @@ -823,11 +879,13 @@ def create_config(case=None, Exp='Dummy', Type='Tor', any([pp is not None for pp in lp])] if np.sum(lc) > 1: msg = ("Please provide either:\n" - + "\t- case: the name of a stored case\n" - + "\t- geometrical parameters {}".format(lpstr)) + + "\t- case: the name of a pre-defined config\n" + + "\t- geometrical parameters {}\n\n".format(lpstr)) raise Exception(msg) elif not any(lc): - case = _DEFCONFIG + msg = get_available_config(verb=False, returnas=str) + raise Exception(msg) + # case = _DEFCONFIG # Get config, either from known case or geometrical parameterization if case is not None: diff --git a/tofu/version.py b/tofu/version.py index 7b58261e4..3c7f44519 100644 --- a/tofu/version.py +++ b/tofu/version.py @@ -1,2 +1,2 @@ # Do not edit, pipeline versioning governed by git tags! -__version__ = '1.4.2-a5-91-g5e9b601a' +__version__ = '1.4.2-a5-71-g56f30784'