Source code for omfit_classes.omfit_json

try:
    # framework is running
    from .startup_choice import *
except ImportError as _excp:
    # class is imported by itself
    if (
        'attempted relative import with no known parent package' in str(_excp)
        or 'No module named \'omfit_classes\'' in str(_excp)
        or "No module named '__main__.startup_choice'" in str(_excp)
    ):
        from startup_choice import *
    else:
        raise

from omfit_classes.omfit_ascii import OMFITascii
from omfit_classes.utils_math import is_uncertain
from omfit_classes import namelist

from scipy import signal
import json

# Import both numpy and numpy as np to support evaluation of expressions
import numpy
import numpy as np

__all__ = ['OMFITjson', 'OMFITsettings', 'SettingsName']


def u2s(x, dctType):
    if isinstance(x, str):
        xs = x.encode('utf-8')
        if xs == x:
            return xs
    elif isinstance(x, list):
        return list([u2s(x, dctType) for x in x])
    elif isinstance(x, dict):
        return loader(list(x.items()), dctType)
    return x


# json loader/dumper are borrowed from OMAS
from omas.omas_utils import json_dumper

# customize json_dumper for OMFIT
def dumper(obj, objects_encode=True):
    if isinstance_str(obj, ['OMFITexpression', 'OMFITiterableExpression']):
        return evalExpr(obj)
    else:
        return json_dumper(obj, objects_encode=objects_encode)


from omas.omas_utils import json_loader

# customize json_loader for OMFIT
def loader(object_pairs, dctType):
    object_pairs = list([(u2s(o[0], dctType), u2s(o[1], dctType)) for o in object_pairs])
    return json_loader(object_pairs, dctType)


[docs]class OMFITjson(SortedDict, OMFITascii): """ OMFIT class to read/write json files """ baseDict = SortedDict def __init__(self, filename, use_leading_comma=None, add_top_level_brackets=False, objects_encode=True, **kw): r''' OMFIT class to parse json files :param filename: filename of the json file :param use_leading_comma: whether commas whould be leading :param add_top_level_brackets: whether to add opening `{` and closing `}` to string read from file :param \**kw: arguments passed to __init__ of OMFITascii ''' OMFITascii.__init__(self, filename, **kw) SortedDict.__init__(self) self.use_leading_comma = use_leading_comma self.add_top_level_brackets = add_top_level_brackets self.objects_encode = objects_encode self.dynaLoad = True @property def use_leading_comma(self): return self.OMFITproperties['use_leading_comma'] @use_leading_comma.setter def use_leading_comma(self, use_leading_comma): self.OMFITproperties['use_leading_comma'] = use_leading_comma @property def add_top_level_brackets(self): return self.OMFITproperties['add_top_level_brackets'] @add_top_level_brackets.setter def add_top_level_brackets(self, add_top_level_brackets): self.OMFITproperties['add_top_level_brackets'] = add_top_level_brackets
[docs] @dynaLoad def load(self): with open(self.filename, 'r') as f: tmp = f.read().strip() if not len(tmp): return if self.add_top_level_brackets: if not isinstance(self.add_top_level_brackets, str): raise ValueError("`add_top_level_brackets` should be either '{}' or '[]'") if "{" in self.add_top_level_brackets: tmp = "\n".join(["{", tmp.rstrip(','), "}"]) elif "[" in self.add_top_level_brackets: tmp = "\n".join(["[", tmp.rstrip(','), "]"]) else: raise ValueError("`add_top_level_brackets` should be either '{}' or '[]'") self.add_top_level_brackets = False self.update(json.loads(tmp, object_pairs_hook=lambda obj: loader(obj, self.baseDict))) # figure out if the style of this json is to have a leading comma if self.use_leading_comma is None: trailing_commas = tmp.count(',\n') leading_commas = re.subn('\n(\\s+),', '', tmp)[1] # https://stackoverflow.com/a/1374893/6605826 use_leading_comma = leading_commas > trailing_commas self.use_leading_comma = leading_commas > trailing_commas
[docs] @dynaSave def save(self): with open(self.filename, 'w') as f: output = json.dumps(self, default=lambda x: dumper(x, self.objects_encode), indent=1, separators=(',', ': ')) if self.use_leading_comma: output = re.sub(r",\n(\s+)", r"\n\1,", output) f.write(output + '\n')
def __save_kw__(self): """ :return: kw dictionary used to save the attributes to be passed when reloading from OMFITsave.txt """ tmp = self.OMFITproperties.copy() if 'use_leading_comma' in tmp and not tmp['use_leading_comma']: tmp.pop('use_leading_comma') if 'add_top_level_brackets' in tmp and not tmp['add_top_level_brackets']: tmp.pop('add_top_level_brackets') if 'objects_encode' in tmp and tmp['objects_encode']: tmp.pop('objects_encode') return tmp def __setitem__(self, key, value): if isinstance(key, (np.int64, np.int32)): key = int(key) return super().__setitem__(key, value)
[docs]class SettingsName(SortedDict): """ Class used for dict-types under OMFITsettings """ baseDict = None def __setitem__(self, key, value): if isinstance(key, (np.int64, np.int32)): key = int(key) if isinstance(value, dict) and not isinstance(value, self.baseDict): tmp = self.baseDict() tmp.update(value) value = tmp return super().__setitem__(key, value) def __repr__(self): # we use a simple dictionary representation of Settings # to allow nice editing of settings in the OMFIT GUIs return self.todict().__repr__()
SettingsName.baseDict = SettingsName
[docs]class OMFITsettings(OMFITjson): """ OMFIT class to read/write modules settings """ baseDict = SettingsName def __init__(self, filename, **kw): super().__init__(filename, **kw) self.caseInsensitive = True
[docs] @dynaLoad def load(self): """ load as json and if it fails, load as namelist """ try: super().load() except Exception as _excp: tmp = namelist.NamelistFile(self.filename) self.update(tmp)
def __setitem__(self, key, value): if isinstance(value, dict) and not isinstance(value, self.baseDict): tmp = self.baseDict() tmp.update(value) value = tmp return super().__setitem__(key, value)
def sanitize_all_settings(): for_all_modules( doThis=''' fname = os.path.split(moduleFile)[0] + os.sep + os.path.split(root['SETTINGS'].filename)[1] root['SETTINGS']=OMFITsettings(fname) root['SETTINGS'].load() root['SETTINGS'].use_leading_comma = False root['SETTINGS'].deploy(fname) ''', deploy=False, skip=False, ) ############################################ if '__main__' == __name__: test_classes_main_header() settings = OMFITjson(OMFITsrc + '/../modules/EFIT/SettingsNamelist.txt', use_leading_comma=True) print('leading comma', settings.OMFITproperties.get('use_leading_comma', None))