-
Notifications
You must be signed in to change notification settings - Fork 13
Issue #351 tofu-custom #353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
68e3ec0
8a409da
919e2cb
8ab2519
6becc22
644741c
4a7f26d
ee6a0f4
cd441ad
6b48154
f62da38
710f0d0
0b5962b
baa2ddb
4622b31
f5b4781
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,8 +11,10 @@ | |
| try: | ||
| try: | ||
| from tofu.imas2tofu._core import * | ||
| from tofu.imas2tofu._mat2ids2calc import * | ||
| except Exception: | ||
| from ._core import * | ||
| from ._mat2ids2calc import * | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a reason why you do an "import *" ? is it just because the file is small?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's because the file is small and also because it contains a very specific use-case that may get generalized later, in which case we'll be happy to have it in a separate module that we can import (becasue it would then get bigger) Thanks ! |
||
| except Exception as err: | ||
| if str(err) == 'imas not available': | ||
| msg = "" | ||
|
|
||
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,205 @@ | ||
|
|
||
| # Built-in | ||
| import os | ||
|
|
||
| # Common | ||
| import scipy.io as scpio | ||
| import numpy as np | ||
|
|
||
| # tofu-specific | ||
| from .. import _physics | ||
|
|
||
|
|
||
| __all__ = ['get_data_from_matids'] | ||
| _LIDSOK = ['core_profiles'] | ||
| _DRETURN = {'core_profiles': ['rhotn', 'ne', 'Te', 'zeff', 't', 'brem']} | ||
| _MSG0 = ("The input file structure is not as expected !\n" | ||
| + " => Maybe file structure changed ?\n" | ||
| + " => Maybe corrupted data ?\n") | ||
|
|
||
|
|
||
| # #################################################### | ||
| # Utility | ||
| # #################################################### | ||
|
|
||
| def _get_indtlim(t, tlim=None, shot=None, out=bool): | ||
| """ """ | ||
| c0 = tlim is None | ||
| c1 = type(tlim) in [list, tuple, np.ndarray] | ||
| assert c0 or c1 | ||
| assert type(t) is np.ndarray | ||
|
|
||
| if c0: | ||
| tlim = [-np.inf, np.inf] | ||
| else: | ||
| assert len(tlim) == 2 | ||
| ls = [int, float, np.int64, np.float64] # , str | ||
| assert all([tt is None or type(tt) in ls for tt in tlim]) | ||
| tlim = list(tlim) | ||
| for (ii, sgn) in [(0, -1.), (1, 1.)]: | ||
| if tlim[ii] is None: | ||
| tlim[ii] = sgn*np.inf | ||
| # elif type(tlim[ii]) is str and 'ign' in tlim[ii].lower(): | ||
| # tlim[ii] = get_t0(shot) | ||
|
|
||
| assert tlim[0] < tlim[1] | ||
| indt = (t >= tlim[0]) & (t <= tlim[1]) | ||
| if out is int: | ||
| indt = indt.nonzero()[0] | ||
| return indt | ||
|
|
||
|
|
||
| # #################################################### | ||
| # Main function | ||
| # #################################################### | ||
|
|
||
| def get_data_from_matids(input_pfe=None, tlim=None, | ||
| return_fields=None, lamb=None): | ||
| """ Extract tofu-compatible from an ids saved as a mat file | ||
|
|
||
| Assumes that the mat file contains the ids data | ||
| Only the following ids are handled: | ||
| {} | ||
|
|
||
| """.format(_LIDSOK) | ||
|
|
||
| # --------------- | ||
| # Check | ||
| if not os.path.isfile(input_pfe): | ||
| msg = ("Provided file does not seem to exist:\n" | ||
| + "\t- {}".format(input_pfe)) | ||
| raise Exception(msg) | ||
| lc = [return_fields is None, | ||
| isinstance(return_fields, str), | ||
| isinstance(return_fields, list) | ||
| and all([isinstance(ss, str) for ss in return_fields])] | ||
| if not any(lc): | ||
| msg = "return_fields must be a str or a list of str " | ||
| raise Exception(msg) | ||
| if lc[1]: | ||
| return_fields = [return_fields] | ||
|
|
||
| # --------------- | ||
| # Load and check / extract ids | ||
| mat = scpio.loadmat(input_pfe) | ||
| ids = [k0 for k0 in mat.keys() if '__' not in k0] | ||
| if len(ids) != 1 or ids[0] not in _LIDSOK: | ||
| msg = ("The file does not seem to contain a known ids:\n" | ||
| + "\t- file: {}\n".format(input_pfe) | ||
| + "\t- keys: {}\n".format(sorted(mat.keys())) | ||
| + "\t- known ids: {}".format(_LIDSOK)) | ||
| raise Exception(msg) | ||
| ids = ids[0] | ||
| data = mat[ids] | ||
|
|
||
| if return_fields is None: | ||
| return_fields = _DRETURN[ids] | ||
| notok = [ss for ss in return_fields if ss not in _DRETURN[ids]] | ||
| if len(notok) > 0: | ||
| msg = ("Some requested fields are not available:\n" | ||
| + "\t- requested: {}\n".format(notok) | ||
| + "\t- available: {}".format(_DRETURN[ids])) | ||
| raise Exception(msg) | ||
|
|
||
| # --------------- | ||
| # Get inside ids and extract data | ||
| if ids == 'core_profiles': | ||
| # --------------- | ||
| # Check expected structure | ||
| if not (data.shape == (1, 1) and data[0, 0].size == 1): | ||
| msg = ("\t{}.shape = {}\n".format(ids, data.shape) | ||
| + "\t{}.size = {}".format(ids, data[0, 0].size)) | ||
| raise Exception(_MSG0 + msg) | ||
| data = data[0, 0].tolist() | ||
| if not (isinstance(data, tuple) and len(data) == 6): | ||
| msg = ("\ttype({}[0, 0].tolist()) = {}\n".format(ids, type(data)) | ||
| + "\tlen({}[0, 0].tolist()) = {}".format(ids, len(data))) | ||
| raise Exception(_MSG0 + msg) | ||
|
|
||
| ls = [pp.shape for pp in data] | ||
| c0 = [len(ss) == 2 for ss in ls] | ||
| c1 = np.sum([ss == (1, 1) for ss in ls]) == 4 | ||
| c2 = np.sum([(ss[1] == 1 and ss[0] > ss[1]) for ss in ls]) == 1 | ||
| c3 = np.sum([(ss[0] == 1 and ss[1] > ss[0]) for ss in ls]) == 1 | ||
| if c0 and c1 and c2 and c3: | ||
| indt = [ii for ii in range(len(ls)) if ls[ii][0] > ls[ii][1]] | ||
| indp = [ii for ii in range(len(ls)) if ls[ii][0] < ls[ii][1]] | ||
| else: | ||
| if np.sum([ss == (1, 1) for ss in ls]) == 6: | ||
| warnings.warn("There seems to be only one time step...") | ||
| indt = [ii for ii in range(len(ls)) if data[ii].dtype == '<f8'] | ||
| indp = [ii for ii in range(len(ls)) if data[ii].dtype == 'O'] | ||
| else: | ||
| msg = "\t{} contains shapes {}".format(ids, ls) | ||
| raise Exception(_MSG0 + msg) | ||
|
|
||
| if len(indt) != 1 or len(indp) != 1: | ||
| msg = ("\tseveral options for time / profile arrays:\n" | ||
| + "\t\t- len(indt) = {}\n".format(len(indt)) | ||
| + "\t\t- len(indp) = {}".format(len(indp))) | ||
| raise Exception(_MSG0 + msg) | ||
| indt, indp = indt[0], indp[0] | ||
|
|
||
| if not data[indt].size == data[indp].size: | ||
| msg = "\tTime vector and profiles have different sizes !" | ||
| raise Exception(_MSG0 + msg) | ||
|
|
||
| # --------------- | ||
| # Get time vector | ||
| t = data[indt].ravel().astype(float) | ||
| indt = _get_indtlim(t, tlim=tlim, shot=None, out=int) | ||
| t = t[indt] | ||
| nt = t.size | ||
|
|
||
| dout = {} | ||
| if 't' in return_fields: | ||
| dout['t'] = t | ||
|
|
||
| # --------------- | ||
| # Continue checks and get indices of quantities | ||
| data = data[indp].ravel()[indt] | ||
| assert all([pp.shape == (1, 1) for pp in data]) | ||
|
|
||
| des = [ss[0] for ss in data[0][0, 0].dtype.descr] | ||
|
|
||
| if 'rhotn' in return_fields: | ||
| indg = [ii for ii in range(len(des)) if des[ii] == 'grid'][0] | ||
| desg = [ss[0] for ss in data[0][0, 0][indg].dtype.descr] | ||
| indrhotn = [ii for ii in range(len(desg)) | ||
| if desg[ii] == 'rho_tor_norm'][0] | ||
| dout['rhotn'] = np.array([ | ||
| data[ii][0, 0][indg][0, 0][indrhotn].ravel() | ||
| for ii in range(nt)]) | ||
|
|
||
| if 'brem' in return_fields or 'zeff' in return_fields: | ||
| indZeff = [ii for ii in range(len(des)) | ||
| if des[ii] == 'zeff'][0] | ||
| zeff = np.array([data[ii][0, 0][indZeff].ravel() | ||
| for ii in range(nt)]) | ||
| if 'zeff' in return_fields: | ||
| dout['zeff'] = zeff | ||
|
|
||
| if any([ss in return_fields for ss in ['brem', 'Te', 'ne']]): | ||
| inde = [ii for ii in range(len(des)) if des[ii] == 'electrons'][0] | ||
| dese = [ss[0] for ss in data[0][0, 0][inde].dtype.descr] | ||
|
|
||
| if 'brem' in return_fields or 'Te' in return_fields: | ||
| indTe = [ii for ii in range(len(dese)) | ||
| if dese[ii] == 'temperature'][0] | ||
| Te = np.array([data[ii][0, 0][inde][0, 0][indTe].ravel() | ||
| for ii in range(nt)]) | ||
| if 'Te' in return_fields: | ||
| dout['Te'] = Te | ||
|
|
||
| if 'brem' in return_fields or 'ne' in return_fields: | ||
| indne = [ii for ii in range(len(dese)) | ||
| if dese[ii] == 'density'][0] | ||
| ne = np.array([data[ii][0, 0][inde][0, 0][indne].ravel() | ||
| for ii in range(nt)]) | ||
| if 'ne' in return_fields: | ||
| dout['ne'] = ne | ||
|
|
||
| if 'brem' in return_fields: | ||
| dout['brem'] = _physics.compute_bremzeff(Te=Te, ne=ne, | ||
| zeff=zeff, lamb=lamb)[0] | ||
| return dout |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)