h5rdmtoolbox 0.8.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of h5rdmtoolbox might be problematic. Click here for more details.
- h5rdmtoolbox/__init__.py +174 -0
- h5rdmtoolbox/_cfg.py +102 -0
- h5rdmtoolbox/_cli.py +211 -0
- h5rdmtoolbox/_repr.py +480 -0
- h5rdmtoolbox/_user.py +105 -0
- h5rdmtoolbox/_version.py +6 -0
- h5rdmtoolbox/cache.py +3 -0
- h5rdmtoolbox/consts.py +3 -0
- h5rdmtoolbox/conventions/__init__.py +28 -0
- h5rdmtoolbox/conventions/cfg.py +2 -0
- h5rdmtoolbox/conventions/consts.py +22 -0
- h5rdmtoolbox/conventions/core.py +484 -0
- h5rdmtoolbox/conventions/errors.py +34 -0
- h5rdmtoolbox/conventions/html/template.html +17 -0
- h5rdmtoolbox/conventions/layout/__init__.py +35 -0
- h5rdmtoolbox/conventions/layout/core.py +236 -0
- h5rdmtoolbox/conventions/layout/tbx.py +123 -0
- h5rdmtoolbox/conventions/layout/utils.py +25 -0
- h5rdmtoolbox/conventions/layout/validation.py +501 -0
- h5rdmtoolbox/conventions/layout/validators.py +229 -0
- h5rdmtoolbox/conventions/references.py +66 -0
- h5rdmtoolbox/conventions/standard_attributes.py +252 -0
- h5rdmtoolbox/conventions/standard_names/__init__.py +6 -0
- h5rdmtoolbox/conventions/standard_names/accessor.py +130 -0
- h5rdmtoolbox/conventions/standard_names/affixes.py +306 -0
- h5rdmtoolbox/conventions/standard_names/cache.py +3 -0
- h5rdmtoolbox/conventions/standard_names/consts.py +17 -0
- h5rdmtoolbox/conventions/standard_names/h5interface.py +167 -0
- h5rdmtoolbox/conventions/standard_names/name.py +114 -0
- h5rdmtoolbox/conventions/standard_names/table.py +916 -0
- h5rdmtoolbox/conventions/standard_names/transformation.py +267 -0
- h5rdmtoolbox/conventions/standard_names/utils.py +67 -0
- h5rdmtoolbox/conventions/standard_names/validator.py +88 -0
- h5rdmtoolbox/conventions/utils.py +153 -0
- h5rdmtoolbox/conventions/validator_management.py +2 -0
- h5rdmtoolbox/conventions/validators.py +381 -0
- h5rdmtoolbox/conventions/warnings.py +5 -0
- h5rdmtoolbox/data/__init__.py +9 -0
- h5rdmtoolbox/data/fluid-v1.yml +36 -0
- h5rdmtoolbox/data/h5tbx_convention.yaml +21 -0
- h5rdmtoolbox/data/piv-v1.yml +35 -0
- h5rdmtoolbox/data/style.css +199 -0
- h5rdmtoolbox/data/tutorial_convention.yaml +98 -0
- h5rdmtoolbox/data/tutorial_standard_name_table.yaml +89 -0
- h5rdmtoolbox/database/__init__.py +72 -0
- h5rdmtoolbox/database/file.py +497 -0
- h5rdmtoolbox/database/files.py +142 -0
- h5rdmtoolbox/database/lazy.py +151 -0
- h5rdmtoolbox/database/mongo.py +291 -0
- h5rdmtoolbox/database/parallel.py +57 -0
- h5rdmtoolbox/database/results.py +0 -0
- h5rdmtoolbox/database/tutorial.py +6 -0
- h5rdmtoolbox/errors.py +4 -0
- h5rdmtoolbox/extensions/__init__.py +0 -0
- h5rdmtoolbox/extensions/dataset.py +0 -0
- h5rdmtoolbox/extensions/ipyvolume.py +176 -0
- h5rdmtoolbox/extensions/magnitude.py +77 -0
- h5rdmtoolbox/extensions/normalize.py +93 -0
- h5rdmtoolbox/extensions/scatterhist.py +100 -0
- h5rdmtoolbox/extensions/units.py +23 -0
- h5rdmtoolbox/extensions/vector.py +85 -0
- h5rdmtoolbox/hdfgui.py +39 -0
- h5rdmtoolbox/orcid.py +139 -0
- h5rdmtoolbox/plotting.py +166 -0
- h5rdmtoolbox/protected_attributes.py +9 -0
- h5rdmtoolbox/tutorial.py +318 -0
- h5rdmtoolbox/utils.py +481 -0
- h5rdmtoolbox/wrapper/__init__.py +9 -0
- h5rdmtoolbox/wrapper/accessory.py +74 -0
- h5rdmtoolbox/wrapper/core.py +2140 -0
- h5rdmtoolbox/wrapper/ds_decoder.py +109 -0
- h5rdmtoolbox/wrapper/h5attr.py +239 -0
- h5rdmtoolbox/wrapper/h5ext.py +20 -0
- h5rdmtoolbox/wrapper/h5utils.py +32 -0
- h5rdmtoolbox/wrapper/h5yaml.py +78 -0
- h5rdmtoolbox/wrapper/xr2hdf.py +101 -0
- h5rdmtoolbox-0.8.1.dist-info/LICENSE +674 -0
- h5rdmtoolbox-0.8.1.dist-info/METADATA +223 -0
- h5rdmtoolbox-0.8.1.dist-info/RECORD +115 -0
- h5rdmtoolbox-0.8.1.dist-info/WHEEL +5 -0
- h5rdmtoolbox-0.8.1.dist-info/entry_points.txt +2 -0
- h5rdmtoolbox-0.8.1.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/conventions/__init__.py +0 -0
- tests/conventions/standard_attributes/__init__.py +0 -0
- tests/conventions/standard_attributes/standard_names/__init__.py +0 -0
- tests/conventions/standard_attributes/standard_names/test_interface.py +131 -0
- tests/conventions/standard_attributes/standard_names/test_provenance.py +95 -0
- tests/conventions/standard_attributes/standard_names/test_snt.py +238 -0
- tests/conventions/standard_attributes/standard_names/test_transformations_and_affixes.py +268 -0
- tests/conventions/standard_attributes/test_standard_attributes.py +481 -0
- tests/conventions/standard_attributes/test_standard_names.py +296 -0
- tests/conventions/test_conventions.py +285 -0
- tests/conventions/test_layout.py +513 -0
- tests/conventions/test_utils.py +48 -0
- tests/conventions/test_validators.py +27 -0
- tests/database/__init__.py +0 -0
- tests/database/test_filequery.py +474 -0
- tests/database/test_mongo.py +252 -0
- tests/test_config.py +79 -0
- tests/test_extensions.py +160 -0
- tests/test_logger.py +31 -0
- tests/test_orcid.py +32 -0
- tests/test_potting.py +155 -0
- tests/test_repr.py +79 -0
- tests/test_user.py +56 -0
- tests/test_utils.py +94 -0
- tests/test_version.py +19 -0
- tests/wrapper/__init__.py +0 -0
- tests/wrapper/test_core.py +696 -0
- tests/wrapper/test_dump.py +21 -0
- tests/wrapper/test_file.py +503 -0
- tests/wrapper/test_find.py +36 -0
- tests/wrapper/test_h5ext.py +22 -0
- tests/wrapper/test_xr2df.py +41 -0
h5rdmtoolbox/__init__.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""h5rdtoolbox repository"""
|
|
2
|
+
import atexit
|
|
3
|
+
import pathlib
|
|
4
|
+
# noinspection PyUnresolvedReferences
|
|
5
|
+
import pint_xarray
|
|
6
|
+
import shutil
|
|
7
|
+
import xarray as xr
|
|
8
|
+
from typing import Union, Callable
|
|
9
|
+
|
|
10
|
+
from h5rdmtoolbox._cfg import set_config, get_config, get_ureg
|
|
11
|
+
|
|
12
|
+
pint_xarray.unit_registry = get_ureg()
|
|
13
|
+
|
|
14
|
+
from . import conventions
|
|
15
|
+
from .conventions.core import Convention
|
|
16
|
+
from . import plotting
|
|
17
|
+
from . import wrapper
|
|
18
|
+
from ._user import UserDir
|
|
19
|
+
from ._version import __version__
|
|
20
|
+
from . import database
|
|
21
|
+
from . import utils
|
|
22
|
+
from .wrapper.core import lower, Lower, File, Group, Dataset
|
|
23
|
+
from . import errors
|
|
24
|
+
|
|
25
|
+
from .wrapper.accessory import register_special_dataset
|
|
26
|
+
|
|
27
|
+
name = 'h5rdmtoolbox'
|
|
28
|
+
__this_dir__ = pathlib.Path(__file__).parent
|
|
29
|
+
__author__ = 'Matthias Probst'
|
|
30
|
+
__author_orcid__ = 'https://orcid.org/0000-0001-8729-0482'
|
|
31
|
+
|
|
32
|
+
logger = utils.create_tbx_logger('h5rdmtoolbox')
|
|
33
|
+
|
|
34
|
+
logger.setLevel(get_config()['init_logger_level'])
|
|
35
|
+
|
|
36
|
+
cv_h5py = conventions.Convention('h5py',
|
|
37
|
+
contact=__author_orcid__)
|
|
38
|
+
cv_h5py.register()
|
|
39
|
+
|
|
40
|
+
cv_h5tbx = conventions.Convention.from_yaml(__this_dir__ / 'data/h5tbx_convention.yaml')
|
|
41
|
+
|
|
42
|
+
use = conventions.core.use
|
|
43
|
+
|
|
44
|
+
use(get_config()['default_convention'])
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class FileDB:
|
|
48
|
+
"""User-friendly interface to database.Folder, database.File or database.Files"""
|
|
49
|
+
|
|
50
|
+
def __new__(cls, path, rec=False, **kwargs):
|
|
51
|
+
if isinstance(path, (list, tuple)):
|
|
52
|
+
filenames = []
|
|
53
|
+
for p in [pathlib.Path(_p) for _p in path]:
|
|
54
|
+
if p.is_file():
|
|
55
|
+
filenames.append(p)
|
|
56
|
+
elif p.is_dir():
|
|
57
|
+
if rec:
|
|
58
|
+
for f in p.rglob('*.hdf'):
|
|
59
|
+
filenames.append(f)
|
|
60
|
+
else:
|
|
61
|
+
for f in p.glob('*.hdf'):
|
|
62
|
+
filenames.append(f)
|
|
63
|
+
return database.Files(filenames, **kwargs)
|
|
64
|
+
|
|
65
|
+
path = pathlib.Path(path)
|
|
66
|
+
if path.is_dir():
|
|
67
|
+
return database.Folder(path, rec=rec, **kwargs)
|
|
68
|
+
return database.File(path, **kwargs)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def dump(src: Union[str, File, pathlib.Path]) -> None:
|
|
72
|
+
"""Call h5.dump() on the provided HDF5 file
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
src : str, File, pathlib.Path
|
|
77
|
+
the HDF5 file or filename to dump
|
|
78
|
+
"""
|
|
79
|
+
if isinstance(src, File):
|
|
80
|
+
with File(src.hdf_filename) as h5:
|
|
81
|
+
return h5.dump()
|
|
82
|
+
with File(src) as h5:
|
|
83
|
+
return h5.dump()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def dumps(src: Union[str, File, pathlib.Path]):
|
|
87
|
+
"""Call h5.dumps() on the provided HDF5 file"""
|
|
88
|
+
if isinstance(src, File):
|
|
89
|
+
with File(src.hdf_filename) as h5:
|
|
90
|
+
return h5.dumps()
|
|
91
|
+
with File(src) as h5:
|
|
92
|
+
return h5.dumps()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def register_dataset_decoder(decoder: Callable, decoder_name: str = None, overwrite: bool = False):
|
|
96
|
+
"""A decoder function takes a xarray.DataArray and a dataset as input and returns a xarray.DataArray
|
|
97
|
+
It is called after the dataset is loaded into memory and before being returned to the user. Be careful:
|
|
98
|
+
Multiple decoders can be registered and they are called in the order of registration. Hence, your decoder
|
|
99
|
+
may behave unexpectedly!
|
|
100
|
+
"""
|
|
101
|
+
from .wrapper import ds_decoder
|
|
102
|
+
if decoder_name is None:
|
|
103
|
+
decoder_name = decoder.__name__
|
|
104
|
+
registered_decorators = ds_decoder.registered_dataset_decoders
|
|
105
|
+
if decoder_name in registered_decorators or decoder in registered_decorators.values():
|
|
106
|
+
if not overwrite:
|
|
107
|
+
raise ValueError(f'decoder "{decoder_name}" already registered. Name and function must be unique.')
|
|
108
|
+
ds_decoder.registered_dataset_decoders[decoder_name] = decoder
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
atexit_verbose = False
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@atexit.register
|
|
115
|
+
def clean_temp_data(full: bool = False):
|
|
116
|
+
"""cleaning up the tmp directory"""
|
|
117
|
+
from ._user import _user_root_dir
|
|
118
|
+
|
|
119
|
+
failed_dirs = []
|
|
120
|
+
failed_dirs_file = UserDir['tmp'] / 'failed.txt'
|
|
121
|
+
if full:
|
|
122
|
+
root_tmp = _user_root_dir / 'tmp'
|
|
123
|
+
if root_tmp.exists():
|
|
124
|
+
try:
|
|
125
|
+
shutil.rmtree(root_tmp)
|
|
126
|
+
root_tmp.mkdir(exist_ok=True, parents=True)
|
|
127
|
+
except PermissionError as e:
|
|
128
|
+
print(f'removing tmp folder "{root_tmp}" failed due to "{e}".')
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
for _tmp_session_dir in [UserDir['tmp'], ]:
|
|
132
|
+
if atexit_verbose:
|
|
133
|
+
print(f'cleaning up tmp directory "{_tmp_session_dir}"')
|
|
134
|
+
if _tmp_session_dir.exists():
|
|
135
|
+
try:
|
|
136
|
+
if atexit_verbose:
|
|
137
|
+
print(f'try deleting tmp in session dir: {_tmp_session_dir}')
|
|
138
|
+
shutil.rmtree(_tmp_session_dir)
|
|
139
|
+
except PermissionError as e:
|
|
140
|
+
if atexit_verbose:
|
|
141
|
+
print(f'[!] failed deleting tmp session dir: {_tmp_session_dir}')
|
|
142
|
+
failed_dirs.append(UserDir['tmp'])
|
|
143
|
+
if atexit_verbose:
|
|
144
|
+
print(f'removing tmp folder "{_tmp_session_dir}" failed due to "{e}". Best is you '
|
|
145
|
+
f'manually delete the directory.')
|
|
146
|
+
finally:
|
|
147
|
+
lines = []
|
|
148
|
+
if failed_dirs_file.exists():
|
|
149
|
+
with open(failed_dirs_file, 'r') as f:
|
|
150
|
+
lines = f.readlines()
|
|
151
|
+
for line in lines:
|
|
152
|
+
try:
|
|
153
|
+
shutil.rmtree(line.strip())
|
|
154
|
+
except Exception:
|
|
155
|
+
if pathlib.Path(line).exists():
|
|
156
|
+
failed_dirs.append(line)
|
|
157
|
+
|
|
158
|
+
if lines or failed_dirs:
|
|
159
|
+
with open(failed_dirs_file, 'w') as f:
|
|
160
|
+
for fd in failed_dirs:
|
|
161
|
+
f.writelines(f'{fd}\n')
|
|
162
|
+
else:
|
|
163
|
+
failed_dirs_file.unlink(missing_ok=True)
|
|
164
|
+
else:
|
|
165
|
+
logger.debug(f'No user tmp dir not found: {_tmp_session_dir}')
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
xr.set_options(display_expand_data=False)
|
|
169
|
+
|
|
170
|
+
__all__ = ('__version__', '__author__', '__author_orcid__', 'UserDir', 'use',
|
|
171
|
+
'File', 'Group', 'Dataset',
|
|
172
|
+
'dump', 'dumps', 'cv_h5py', 'lower', 'Lower',
|
|
173
|
+
'set_config', 'get_config', 'get_ureg',
|
|
174
|
+
'Convention')
|
h5rdmtoolbox/_cfg.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""package configuration. largely based on xarray's configuration concept. no credits taken!"""
|
|
2
|
+
from pint import UnitRegistry
|
|
3
|
+
from typing import Dict, Union
|
|
4
|
+
|
|
5
|
+
ureg = UnitRegistry(force_ndarray_like=True)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def is_valid_logger_level(level: Union[str, int]):
|
|
9
|
+
"""Check if the logger level is valid."""
|
|
10
|
+
if not isinstance(level, (str, int)):
|
|
11
|
+
# raise TypeError(f'Invalid type for the logger: {type(logger_value)}')
|
|
12
|
+
return False
|
|
13
|
+
if isinstance(level, str):
|
|
14
|
+
return level.lower() in ('error', 'debug', 'critical', 'warning', 'info', 'fatal', 'warning', 'warn')
|
|
15
|
+
# 0: NOTSET, 10: DEBUG, 20: INFO, 30: WARNING, 40: ERROR, 50: CRITICAL
|
|
16
|
+
return level in (0, 10, 20, 30, 40, 50)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
CONFIG = {'return_xarray': True,
|
|
20
|
+
'advanced_shape_repr': True,
|
|
21
|
+
'natural_naming': True,
|
|
22
|
+
'hdf_compression': 'gzip',
|
|
23
|
+
'hdf_compression_opts': 5,
|
|
24
|
+
'xarray_unit_repr_in_plots': 'in',
|
|
25
|
+
'plotting_name_order': ('plot_name', 'long_name', 'standard_name'),
|
|
26
|
+
'require_unit': True, # datasets require units
|
|
27
|
+
'ureg_format': 'C~',
|
|
28
|
+
'default_convention': 'h5tbx',
|
|
29
|
+
'init_logger_level': 'ERROR',
|
|
30
|
+
'dtime_fmt': '%Y%m%d%H%M%S%f',
|
|
31
|
+
'expose_user_prop_to_attrs': True,
|
|
32
|
+
'scale_attribute_name': 'scale',
|
|
33
|
+
'offset_attribute_name': 'offset',
|
|
34
|
+
'add_provenance': True,
|
|
35
|
+
'ignore_standard_attribute_errors': False,
|
|
36
|
+
'allow_deleting_standard_attributes': False,
|
|
37
|
+
'parallel_find': True, }
|
|
38
|
+
|
|
39
|
+
_VALIDATORS = {
|
|
40
|
+
'return_xarray': lambda x: isinstance(x, bool),
|
|
41
|
+
'advanced_shape_repr': lambda x: isinstance(x, bool),
|
|
42
|
+
'natural_naming': lambda x: isinstance(x, bool),
|
|
43
|
+
'hdf_compression': lambda x: isinstance(x, str),
|
|
44
|
+
'hdf_compression_opts': lambda x: isinstance(x, int),
|
|
45
|
+
'xarray_unit_repr_in_plots': lambda x: x in ('/', '()', '(', '[]', '[', '//', 'in'),
|
|
46
|
+
'plotting_name_order': lambda x: isinstance(x, (tuple, list)) and [xx in ('plot_name', 'long_name', 'standard_name')
|
|
47
|
+
for xx in x],
|
|
48
|
+
'require_unit': lambda x: isinstance(x, bool),
|
|
49
|
+
'ureg_format': lambda x: isinstance(x, str),
|
|
50
|
+
'default_convention': lambda x: str(x) in ('h5py', 'h5tbx', 'None'),
|
|
51
|
+
'init_logger_level': lambda x: is_valid_logger_level(x),
|
|
52
|
+
'dtime_fmt': lambda x: isinstance(x, str),
|
|
53
|
+
'expose_user_prop_to_attrs': lambda x: isinstance(x, bool),
|
|
54
|
+
'scale_attribute_name': lambda x: isinstance(x, str),
|
|
55
|
+
'offset_attribute_name': lambda x: isinstance(x, str),
|
|
56
|
+
'add_provenance': lambda x: isinstance(x, bool),
|
|
57
|
+
'ignore_standard_attribute_errors': lambda x: isinstance(x, bool),
|
|
58
|
+
'parallel_find': lambda x: isinstance(x, bool),
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class set_config:
|
|
63
|
+
"""Set the configuration parameters."""
|
|
64
|
+
|
|
65
|
+
def __init__(self, **kwargs):
|
|
66
|
+
self.old = {}
|
|
67
|
+
for k, v in kwargs.items():
|
|
68
|
+
if k in _VALIDATORS and not _VALIDATORS[k](v):
|
|
69
|
+
raise ValueError(f'Config parameter "{k}" has invalid value: "{v}"')
|
|
70
|
+
if k not in CONFIG:
|
|
71
|
+
raise KeyError(f'Not a configuration key: "{k}"')
|
|
72
|
+
self.old[k] = CONFIG[k]
|
|
73
|
+
if k == 'ureg_format':
|
|
74
|
+
get_ureg().default_format = str(v)
|
|
75
|
+
self._update(kwargs)
|
|
76
|
+
|
|
77
|
+
def __enter__(self):
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
def __exit__(self, *args, **kwargs):
|
|
81
|
+
self._update(self.old)
|
|
82
|
+
|
|
83
|
+
def _update(self, options_dict: Dict):
|
|
84
|
+
CONFIG.update(options_dict)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# set_config = ConfigSetter()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_config(key=None):
|
|
91
|
+
"""Return the configuration parameters."""
|
|
92
|
+
if key is None:
|
|
93
|
+
return CONFIG
|
|
94
|
+
return CONFIG[key]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def get_ureg() -> UnitRegistry:
|
|
98
|
+
"""get unit registry"""
|
|
99
|
+
return ureg
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
set_config(ureg_format=CONFIG['ureg_format'])
|
h5rdmtoolbox/_cli.py
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"""collection of command line interface functions"""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import h5py
|
|
5
|
+
import webbrowser
|
|
6
|
+
from pprint import pprint
|
|
7
|
+
|
|
8
|
+
from . import File
|
|
9
|
+
from ._version import __version__
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main():
|
|
13
|
+
"""main command line interface function"""
|
|
14
|
+
parser = argparse.ArgumentParser(description='h5RDMtoolbox command line interface')
|
|
15
|
+
parser.add_argument('-V', '--version',
|
|
16
|
+
action='version', version=f'%(prog)s {__version__}')
|
|
17
|
+
parser.add_argument('-D', dest='documentation',
|
|
18
|
+
action='store_true',
|
|
19
|
+
help="Opens documentation in browser")
|
|
20
|
+
parser.add_argument('-u', '--user-dirs',
|
|
21
|
+
action='store_true',
|
|
22
|
+
default=False,
|
|
23
|
+
help='Print user directories.')
|
|
24
|
+
parser.add_argument('-d', '--dump',
|
|
25
|
+
type=str,
|
|
26
|
+
required=False,
|
|
27
|
+
default=None,
|
|
28
|
+
help='Dump file content.')
|
|
29
|
+
subparsers = parser.add_subparsers(help='sub-commands help')
|
|
30
|
+
|
|
31
|
+
# LAYOUT
|
|
32
|
+
sp_layout = subparsers.add_parser('layout', help='layout menu')
|
|
33
|
+
sp_layout.set_defaults(cmd='layout')
|
|
34
|
+
sp_layout.add_argument('--list-registered', action='store_true',
|
|
35
|
+
help='List all registered layouts.')
|
|
36
|
+
sp_layout.add_argument('-l', '--layout',
|
|
37
|
+
type=str,
|
|
38
|
+
required=False,
|
|
39
|
+
default=None,
|
|
40
|
+
help='Registered layout name or filename of a layout.')
|
|
41
|
+
sp_layout.add_argument('-c', '--check',
|
|
42
|
+
type=str,
|
|
43
|
+
required=False,
|
|
44
|
+
default=None,
|
|
45
|
+
help='Filename to run check on.')
|
|
46
|
+
sp_layout.add_argument('-r', '--register',
|
|
47
|
+
type=str,
|
|
48
|
+
required=False,
|
|
49
|
+
default=None,
|
|
50
|
+
help='Register the passed HDF file as a layout.')
|
|
51
|
+
|
|
52
|
+
# STANDARD NAME
|
|
53
|
+
sp_standard_name = subparsers.add_parser('standard_name', help='standard name menu')
|
|
54
|
+
sp_standard_name.set_defaults(cmd='standard_name')
|
|
55
|
+
sp_standard_name.add_argument('--list-registered', action='store_true',
|
|
56
|
+
help='List all registered standard name tables.')
|
|
57
|
+
sp_standard_name.add_argument('-t', '--table',
|
|
58
|
+
type=str,
|
|
59
|
+
required=False,
|
|
60
|
+
default=None,
|
|
61
|
+
help='Registered standard name or filename of a standard table.')
|
|
62
|
+
sp_standard_name.add_argument('-f', '--file',
|
|
63
|
+
type=str,
|
|
64
|
+
required=False,
|
|
65
|
+
default=None,
|
|
66
|
+
help='Filename to run check on.')
|
|
67
|
+
# MONGODB
|
|
68
|
+
sp_mongo = subparsers.add_parser('mongodb', help='mongodb menu')
|
|
69
|
+
sp_mongo.set_defaults(cmd='mongodb')
|
|
70
|
+
# sp_mongo.add_argument('list_dbs', nargs='?', default=False, help='List all available databases')
|
|
71
|
+
# sp_mongo.add_argument('list_collections', nargs='?', default=False, help='List all available collections of the '
|
|
72
|
+
# 'selected database')
|
|
73
|
+
sp_mongo.add_argument('--list-dbs', action='store_true')
|
|
74
|
+
sp_mongo.add_argument('--list-collections', action='store_true')
|
|
75
|
+
sp_mongo.add_argument('-i', '--ip',
|
|
76
|
+
type=str,
|
|
77
|
+
required=False,
|
|
78
|
+
default='localhost',
|
|
79
|
+
help='IP address. Default is localhost')
|
|
80
|
+
sp_mongo.add_argument('-p', '--port',
|
|
81
|
+
type=int,
|
|
82
|
+
required=False,
|
|
83
|
+
default=27017,
|
|
84
|
+
help='Port. Default is 27017')
|
|
85
|
+
sp_mongo.add_argument('-d', '--db',
|
|
86
|
+
type=str,
|
|
87
|
+
required=False,
|
|
88
|
+
help='Database')
|
|
89
|
+
sp_mongo.add_argument('-c', '--collection',
|
|
90
|
+
type=str,
|
|
91
|
+
required=False,
|
|
92
|
+
default=False,
|
|
93
|
+
help='Collection')
|
|
94
|
+
sp_mongo.add_argument('-a', '--add',
|
|
95
|
+
type=str,
|
|
96
|
+
required=False,
|
|
97
|
+
default=False,
|
|
98
|
+
help='Add HDF file to database')
|
|
99
|
+
|
|
100
|
+
args = parser.parse_args()
|
|
101
|
+
if args.documentation:
|
|
102
|
+
webbrowser.open('https://matthiasprobst.github.io/h5RDMtoolbox/')
|
|
103
|
+
return
|
|
104
|
+
if args.user_dirs:
|
|
105
|
+
from ._user import UserDir
|
|
106
|
+
pprint(UserDir)
|
|
107
|
+
return
|
|
108
|
+
if args.dump:
|
|
109
|
+
with File(args.dump) as h5:
|
|
110
|
+
h5.sdump()
|
|
111
|
+
arg_vars = vars(args)
|
|
112
|
+
|
|
113
|
+
if 'cmd' in arg_vars:
|
|
114
|
+
if args.cmd == 'mongodb':
|
|
115
|
+
from pymongo import MongoClient
|
|
116
|
+
db = None
|
|
117
|
+
collection = None
|
|
118
|
+
|
|
119
|
+
print(f'\n > Current connection: {args.ip}:{args.port}')
|
|
120
|
+
client = MongoClient(args.ip, args.port)
|
|
121
|
+
list_of_databases = client.list_database_names()
|
|
122
|
+
|
|
123
|
+
if args.db:
|
|
124
|
+
if len(list_of_databases) == 0:
|
|
125
|
+
print(' > No connection to a client found')
|
|
126
|
+
return
|
|
127
|
+
db = client[args.db]
|
|
128
|
+
|
|
129
|
+
if args.collection:
|
|
130
|
+
# list_of_collections = db.list_collection_names()
|
|
131
|
+
# if len(list_of_collections) == 0:
|
|
132
|
+
# print(f' ! No collections found')
|
|
133
|
+
# return
|
|
134
|
+
collection = db[args.collection]
|
|
135
|
+
print(f' > Selected collection: {collection}')
|
|
136
|
+
|
|
137
|
+
if args.list_dbs:
|
|
138
|
+
pprint(list_of_databases)
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
if args.list_collections:
|
|
142
|
+
print(' > Listing collections for ')
|
|
143
|
+
if db is None:
|
|
144
|
+
print(' ! No database selected')
|
|
145
|
+
return
|
|
146
|
+
print(db)
|
|
147
|
+
list_of_collections = db.list_collection_names()
|
|
148
|
+
print(' > List of collections:\n--------------------')
|
|
149
|
+
pprint(list_of_collections)
|
|
150
|
+
return
|
|
151
|
+
|
|
152
|
+
if args.add:
|
|
153
|
+
if collection is None:
|
|
154
|
+
print('No collection selected or found')
|
|
155
|
+
return
|
|
156
|
+
try:
|
|
157
|
+
with h5py.File(args.add):
|
|
158
|
+
pass
|
|
159
|
+
except OSError:
|
|
160
|
+
print(' ! Unable to open the HDF file. Make sure it is an HDF file and that it can be '
|
|
161
|
+
'opened/is not corrupt')
|
|
162
|
+
return
|
|
163
|
+
print(f' > Adding hdf file: {args.add} to collection {collection.name} of database {db.name}')
|
|
164
|
+
with File(args.add) as h5:
|
|
165
|
+
# noinspection PyUnresolvedReferences
|
|
166
|
+
from h5rdmtoolbox.database import mongo
|
|
167
|
+
h5.mongo.insert(collection=collection, recursive=True, update=True)
|
|
168
|
+
return
|
|
169
|
+
if args.cmd == 'standard_name':
|
|
170
|
+
from .conventions.tbx import StandardNameTable
|
|
171
|
+
import pathlib
|
|
172
|
+
if args.list_registered:
|
|
173
|
+
StandardNameTable.print_registered()
|
|
174
|
+
return
|
|
175
|
+
if args.table:
|
|
176
|
+
snt_filename = pathlib.Path(args.table)
|
|
177
|
+
if snt_filename.exists():
|
|
178
|
+
snt = StandardNameTable.from_yaml(args.table)
|
|
179
|
+
else:
|
|
180
|
+
snt = StandardNameTable.load_registered(args.table)
|
|
181
|
+
print(f' > Checking file "{args.file}" with standard name table "{snt.versionname}"')
|
|
182
|
+
with File(args.file) as h5:
|
|
183
|
+
snt.check_hdf_group(h5, recursive=True, raise_error=False)
|
|
184
|
+
return
|
|
185
|
+
if args.cmd == 'layout':
|
|
186
|
+
from .conventions import layout
|
|
187
|
+
import pathlib
|
|
188
|
+
if args.list_registered:
|
|
189
|
+
for k in layout.File.Registry().layouts.keys():
|
|
190
|
+
print(k)
|
|
191
|
+
return
|
|
192
|
+
hdf_filename = None
|
|
193
|
+
if args.check:
|
|
194
|
+
hdf_filename = pathlib.Path(args.check)
|
|
195
|
+
if args.layout:
|
|
196
|
+
layout_filename = pathlib.Path(args.layout)
|
|
197
|
+
if layout_filename.exists():
|
|
198
|
+
h5lay = layout.File(layout_filename)
|
|
199
|
+
else:
|
|
200
|
+
h5lay = layout.File.load_registered(args.layout, h5repr=None)
|
|
201
|
+
if hdf_filename is None:
|
|
202
|
+
print('No hdf filename. Provide by -f <my_file.hdf>')
|
|
203
|
+
return
|
|
204
|
+
print(f'Checking {hdf_filename} with layout {args.layout}')
|
|
205
|
+
with h5py.File(hdf_filename) as h5:
|
|
206
|
+
h5lay.check(h5)
|
|
207
|
+
return
|
|
208
|
+
if args.register:
|
|
209
|
+
hdf_filename = pathlib.Path(args.register)
|
|
210
|
+
h5lay = layout.File(hdf_filename)
|
|
211
|
+
h5lay.register()
|