From 6503b991cbb4744bc64e645b3acd69d283a7ed2b Mon Sep 17 00:00:00 2001 From: VEZINET Didier Date: Mon, 13 Jan 2020 11:56:06 +0100 Subject: [PATCH 1/9] [Issue301] Implemented tf.geom.utils.get_available_config(), with more explicit msg --- tofu/geom/utils.py | 49 +++++++++++++++++++++++++++++++++++++++------- tofu/version.py | 2 +- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index 8bc170ea5..90ce593f8 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -643,6 +643,11 @@ 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 _DCONFIG = {'WEST-V1': {'Exp': _ExpWest, @@ -695,8 +700,40 @@ def _compute_CamLOS2D_pinhole(P=None, F=0.1, D12=0.1, N12=100, 'B4': 'ITER-V2', 'NSTX': 'NSTX-V0'} -# Default config -_DEFCONFIG = 'ITER' + +def _get_listconfig(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, + returnas=str): + assert returnas in [dict, str] + dc = {k0: [k0] + sorted([k1 for k1, v1 in dconfig_table.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 + + +def get_available_config(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, + verb=True, returnas=False): + msg = ("A config is the geometry of a tokamak\n" + + "You can define your own" + + " (see online tutorial at {})\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_table=dconfig_table) + + "\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 is str: + return msg def _create_config_testcase(config=None, returnas='object', @@ -724,11 +761,9 @@ def _create_config_testcase(config=None, returnas='object', config = dconfig_table[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 diff --git a/tofu/version.py b/tofu/version.py index 4fc937bc2..8d70bce59 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-48-gac0016b' +__version__ = '1.4.2-a5-63-ge6c9f42b' From f2f9cb486d10570821acb967585e228f02b59738 Mon Sep 17 00:00:00 2001 From: VEZINET Didier Date: Mon, 13 Jan 2020 12:15:06 +0100 Subject: [PATCH 2/9] [Issue301] PEP8 compliance 1 --- tofu/geom/utils.py | 4 ++-- tofu/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index 90ce593f8..e33a15733 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -713,7 +713,7 @@ def _get_listconfig(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, 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" + "-"*l0 + " \t" + "-"*l1 + "\n\t- " + "\n\t- ".join(["{}\t{}".format(k0.ljust(l0), v0) for k0, v0 in dc.items()])) @@ -721,7 +721,7 @@ def _get_listconfig(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, def get_available_config(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, - verb=True, returnas=False): + verb=True, returnas=False): msg = ("A config is the geometry of a tokamak\n" + "You can define your own" + " (see online tutorial at {})\n".format(_URL_TUTO) diff --git a/tofu/version.py b/tofu/version.py index 8d70bce59..8c2ca6d8b 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-63-ge6c9f42b' +__version__ = '1.4.2-a5-64-g6503b991' From 995809ff6a7d05d94302665b4b8d4d433aa1abfa Mon Sep 17 00:00:00 2001 From: VEZINET Didier Date: Tue, 14 Jan 2020 18:06:38 +0100 Subject: [PATCH 3/9] [Issue301] Error message now used also when user provides no input to tf.geom.utils.create_Config() --- tofu/geom/utils.py | 9 ++++++--- tofu/version.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index e33a15733..4caf5774c 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -858,11 +858,14 @@ 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) + + get_available_config(verb=False, returnas=str)) 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 8c2ca6d8b..56c82a627 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-64-g6503b991' +__version__ = '1.4.2-a5-65-gf2f9cb48' From 11c10608547fe23072bf43acbd118c77b12cc9af Mon Sep 17 00:00:00 2001 From: VEZINET Didier Date: Tue, 14 Jan 2020 18:07:10 +0100 Subject: [PATCH 4/9] [Issue301] Typo --- tofu/geom/utils.py | 3 +-- tofu/version.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index 4caf5774c..230530c42 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -859,8 +859,7 @@ def create_config(case=None, Exp='Dummy', Type='Tor', if np.sum(lc) > 1: msg = ("Please provide either:\n" + "\t- case: the name of a pre-defined config\n" - + "\t- geometrical parameters {}\n\n".format(lpstr) - + get_available_config(verb=False, returnas=str)) + + "\t- geometrical parameters {}\n\n".format(lpstr)) raise Exception(msg) elif not any(lc): msg = get_available_config(verb=False, returnas=str) diff --git a/tofu/version.py b/tofu/version.py index 56c82a627..6b5f1dfa5 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-65-gf2f9cb48' +__version__ = '1.4.2-a5-66-g995809ff' From ef8ffa10567a59c5e7b01bbe0aceb36a2e2175cd Mon Sep 17 00:00:00 2001 From: VEZINET Didier Date: Fri, 17 Jan 2020 15:51:42 +0100 Subject: [PATCH 5/9] [Issue301] Rename _DCONFIG_TABLE -> _DCONFIG_SHORTCUTS --- tofu/geom/utils.py | 40 ++++++++++++++++++++-------------------- tofu/version.py | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index 230530c42..60e8ed5f5 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -688,23 +688,23 @@ def _compute_CamLOS2D_pinhole(P=None, F=0.1, D12=0.1, N12=100, # 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'} - - -def _get_listconfig(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, +_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): assert returnas in [dict, str] - dc = {k0: [k0] + sorted([k1 for k1, v1 in dconfig_table.items() + 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: @@ -720,14 +720,14 @@ def _get_listconfig(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, return msg -def get_available_config(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, +def get_available_config(dconfig=_DCONFIG, dconfig_shortcuts=_DCONFIG_SHORTCUTS, verb=True, returnas=False): msg = ("A config is the geometry of a tokamak\n" + "You can define your own" + " (see online tutorial at {})\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_table=dconfig_table) + + _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: @@ -738,7 +738,7 @@ def get_available_config(dconfig=_DCONFIG, dconfig_table=_DCONFIG_TABLE, 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: @@ -756,9 +756,9 @@ 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 = ("\nThe provided config name is not valid.\n" diff --git a/tofu/version.py b/tofu/version.py index 6b5f1dfa5..85be830a1 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-66-g995809ff' +__version__ = '1.4.2-a5-67-g11c10608' From 2b90034c6e5f0508b85ceb24ffef3a8884849edf Mon Sep 17 00:00:00 2001 From: VEZINET Didier Date: Fri, 17 Jan 2020 16:01:12 +0100 Subject: [PATCH 6/9] [Issue301] Added comments (for dev) and docstr to new method, also included new method in tf.geom.utils.__all__ --- tofu/geom/utils.py | 27 +++++++++++++++++++++++---- tofu/version.py | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index 60e8ed5f5..606d7584c 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'] @@ -650,6 +650,9 @@ def _compute_CamLOS2D_pinhole(P=None, F=0.1, D12=0.1, N12=100, + '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, @@ -685,9 +688,9 @@ 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 +# 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', @@ -703,6 +706,7 @@ def _compute_CamLOS2D_pinhole(P=None, F=0.1, D12=0.1, N12=100, 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]) @@ -722,6 +726,21 @@ def _get_listconfig(dconfig=_DCONFIG, dconfig_shortcuts=_DCONFIG_SHORTCUTS, 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".format(_URL_TUTO) diff --git a/tofu/version.py b/tofu/version.py index 85be830a1..291248db8 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-67-g11c10608' +__version__ = '1.4.2-a5-68-gef8ffa10' From f7444b9a50944e9861e2f5a168d086925401fa39 Mon Sep 17 00:00:00 2001 From: VEZINET Didier Date: Fri, 17 Jan 2020 16:05:32 +0100 Subject: [PATCH 7/9] [Issue301] Better formatted msg (url on its onw line) --- tofu/geom/utils.py | 2 +- tofu/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index 606d7584c..318ff4617 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -743,7 +743,7 @@ def get_available_config(dconfig=_DCONFIG, dconfig_shortcuts=_DCONFIG_SHORTCUTS, """ msg = ("A config is the geometry of a tokamak\n" + "You can define your own" - + " (see online tutorial at {})\n".format(_URL_TUTO) + + ", 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) diff --git a/tofu/version.py b/tofu/version.py index 291248db8..d00696688 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-68-gef8ffa10' +__version__ = '1.4.2-a5-69-g2b90034c' From 56f30784a56c03a8532b898a2c55e0e2c6920b6f Mon Sep 17 00:00:00 2001 From: VEZINET Didier Date: Fri, 17 Jan 2020 16:14:10 +0100 Subject: [PATCH 8/9] [Issue301] PEP8 compliance --- tofu/geom/utils.py | 6 ++++-- tofu/version.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index 318ff4617..af1a8af64 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -724,7 +724,8 @@ def _get_listconfig(dconfig=_DCONFIG, dconfig_shortcuts=_DCONFIG_SHORTCUTS, return msg -def get_available_config(dconfig=_DCONFIG, dconfig_shortcuts=_DCONFIG_SHORTCUTS, +def get_available_config(dconfig=_DCONFIG, + dconfig_shortcuts=_DCONFIG_SHORTCUTS, verb=True, returnas=False): """ Print a table showing all pre-defined config @@ -746,7 +747,8 @@ def get_available_config(dconfig=_DCONFIG, dconfig_shortcuts=_DCONFIG_SHORTCUTS, + ", 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) + + _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: diff --git a/tofu/version.py b/tofu/version.py index d00696688..0b0c8df8e 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-69-g2b90034c' +__version__ = '1.4.2-a5-70-gf7444b9a' From 7a3aca15417e765d80f51e1585a46ebd124ca7d2 Mon Sep 17 00:00:00 2001 From: Didier Date: Fri, 17 Jan 2020 16:45:49 +0100 Subject: [PATCH 9/9] None and True options for returnas are also handled in get_available_config() (default to str) --- tofu/geom/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tofu/geom/utils.py b/tofu/geom/utils.py index af1a8af64..0c16c0c31 100644 --- a/tofu/geom/utils.py +++ b/tofu/geom/utils.py @@ -753,7 +753,7 @@ def get_available_config(dconfig=_DCONFIG, + "\tconfig = tf.geom.utils.create_config('ITER')") if verb is True: print(msg) - if returnas is str: + if returnas in [None, True, str]: return msg