h5rdmtoolbox 2.7.4__tar.gz → 2.8.0__tar.gz
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.
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/PKG-INFO +30 -7
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/README.md +25 -6
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/__init__.py +23 -1
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/cli.py +4 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/__init__.py +4 -1
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/ld/metrics.py +279 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/__init__.py +15 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/chat.py +340 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/errors.py +22 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/executor.py +56 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/interfaces.py +17 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/models.py +85 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/ontology.py +171 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/prompting.py +157 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/providers/__init__.py +6 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/providers/openai_adapter.py +61 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/sparql_guard.py +124 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/llm/summary.py +77 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/server/static/graph.css +337 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/server/static/graph.js +568 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/server/static/style.css +11 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/server/templates/graph.html +127 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/server/templates/index.html +0 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/server/templates/resource.html +0 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/server.py +3211 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/user.py +18 -11
- h5rdmtoolbox-2.8.0/h5rdmtoolbox/wrapper/accessors/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/core.py +27 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox.egg-info/PKG-INFO +30 -7
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox.egg-info/SOURCES.txt +23 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox.egg-info/entry_points.txt +2 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox.egg-info/requires.txt +5 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox.egg-info/top_level.txt +2 -0
- h5rdmtoolbox-2.8.0/h5rdmtoolbox_cli.py +168 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/pyproject.toml +14 -3
- h5rdmtoolbox-2.8.0/tests/test_cli.py +190 -0
- h5rdmtoolbox-2.8.0/tests/test_server.py +1771 -0
- h5rdmtoolbox-2.7.4/h5rdmtoolbox/cli.py +0 -61
- h5rdmtoolbox-2.7.4/h5rdmtoolbox.egg-info/entry_points.txt +0 -2
- h5rdmtoolbox-2.7.4/h5rdmtoolbox.egg-info/top_level.txt +0 -1
- h5rdmtoolbox-2.7.4/tests/test_cli.py +0 -69
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/LICENSE +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/_cfg.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/_repr.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/_version.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/_initialization.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/abstracts.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/core.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/profiles.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/query_templates.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/stores/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/stores/hdf5.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/catalog/utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/consts.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/cfg.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/consts.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/core.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/errors.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/generate.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/ontology/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/ontology/h5ontocls.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/ontology/hdf_datatypes.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/references.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/standard_attributes.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/toolbox_validators.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/convention/utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/def_icon.png +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/fluid-v1.yml +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/h5tbx.yaml +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/id_icon.png +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/iri_icon.png +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/ld_icon.png +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/piv-v1.yml +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/style.css +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/tutorial_convention.yaml +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/tutorial_convention_vfuncs.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/tutorial_standard_name_table.yaml +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/data/type_icon.png +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/hdfdb/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/hdfdb/filedb.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/hdfdb/objdb.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/hdfdb/query.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/hdfdb/utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/interface.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/lazy.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/database/mongo.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/errors.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/extensions/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/extensions/magnitude.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/extensions/normalize.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/extensions/onto.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/extensions/units.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/extensions/vector.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/gui/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/gui/fairify.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/gui/src/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/gui/src/main.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/identifiers.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/layout/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/layout/core.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/_types.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/globals.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/hdf/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/hdf/attributes.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/hdf/datasets.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/hdf/file.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/hdf/groups.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/rdf.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/shacl.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/sparql.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/user/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/user/attributes.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/user/datasets.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/user/file.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/user/groups.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/user/utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/ld/utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/plotting.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/protected_attributes.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/protocols.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/default_metamapper.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/interface.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/zenodo/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/zenodo/core.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/zenodo/metadata.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/zenodo/tokens.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/repository/zenodo/utils.py +0 -0
- /h5rdmtoolbox-2.7.4/h5rdmtoolbox/wrapper/accessors/__init__.py → /h5rdmtoolbox-2.8.0/h5rdmtoolbox/server/templates/file.html +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/tutorial.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/utils/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/utils/docstring.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/utils/download.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/utils/file_io.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/utils/hdf5.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/utils/string.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/__init__.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/accessor.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/accessors/provenance.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/ds_decoder.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/h5attr.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/h5ext.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/h5utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/h5yaml.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/jsonld.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox/wrapper/xr2hdf.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/h5rdmtoolbox.egg-info/dependency_links.txt +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/setup.cfg +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_config.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_extensions.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_identifiers.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_plotting.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_readme.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_repr.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_user.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_utils.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_version.py +0 -0
- {h5rdmtoolbox-2.7.4 → h5rdmtoolbox-2.8.0}/tests/test_xarray_export.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: h5rdmtoolbox
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0
|
|
4
4
|
Summary: Supporting a FAIR Research Data lifecycle using Python and HDF5.
|
|
5
5
|
Author-email: Matthias Probst <matth.probst@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -78,6 +78,10 @@ Provides-Extra: complete
|
|
|
78
78
|
Requires-Dist: h5rdmtoolbox[gui,test]; extra == "complete"
|
|
79
79
|
Provides-Extra: complete-with-docs
|
|
80
80
|
Requires-Dist: h5rdmtoolbox[complete,docs]; extra == "complete-with-docs"
|
|
81
|
+
Provides-Extra: server
|
|
82
|
+
Requires-Dist: fastapi>=0.95; extra == "server"
|
|
83
|
+
Requires-Dist: uvicorn[standard]>=0.22; extra == "server"
|
|
84
|
+
Requires-Dist: jinja2>=3.1; extra == "server"
|
|
81
85
|
Dynamic: license-file
|
|
82
86
|
|
|
83
87
|
# HDF5 Research Data Management Toolbox
|
|
@@ -233,18 +237,37 @@ hdf:H5T_INTEL_I64 a hdf:Datatype .
|
|
|
233
237
|
hdf:size 4 .
|
|
234
238
|
```
|
|
235
239
|
|
|
236
|
-
|
|
240
|
+
## Command Line Interface
|
|
237
241
|
|
|
238
|
-
|
|
242
|
+
The `h5tbx` command provides quick access to linked-data serialization and local inspection from the shell.
|
|
239
243
|
|
|
240
|
-
|
|
244
|
+
Use `h5tbx ld dump example.h5` to print Turtle RDF, or write a specific format with:
|
|
241
245
|
|
|
242
|
-
|
|
246
|
+
```bash
|
|
247
|
+
h5tbx ld dump example.h5 -o example.jsonld
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The dump command accepts `--format`, `--file-uri`, `--prefix`, `--structural=false`, and `--contextual=false`, so you can choose RDF output, assign stable RDF subject URIs, bind a compact prefix, and include only structural or user-provided contextual metadata when needed.
|
|
251
|
+
|
|
252
|
+
To inspect files in a browser, run:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
h5tbx serve example.h5
|
|
256
|
+
h5tbx serve data/ --h5ext=.h5 --h5ext=.hdf5
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
The local web app links to Turtle, JSON-LD, N-Triples, RDF/XML, an interactive graph view, SPARQL query editor, graph metrics, and SHACL validation. Per-file buttons are scoped to that file; the landing page also offers a separate combined graph section for all served files plus loaded enrichment. Combined graph visualization is reduced by default with node/edge limits and search controls, and combined metrics skip exact largest-distance computation on very large graphs to keep the local server responsive. HDF5 object URLs such as `/example.h5/group/dataset` dereference to a browser HTML page by default, while `Accept: text/turtle`, `Accept: application/ld+json`, or `?format=ttl|jsonld|nt|xml|html` return the requested representation. For published DOI-style file URIs, use `/resolve?iri=https://doi.org/...%23path` to resolve an exact external RDF subject locally. The resolver uses the first matching served HDF5 subject, caches all served files in one shared query graph, and enriches that graph with known ontology TTL sources, QUDT unit definitions, Zenodo RDF attachments, generic ontology documents, and Wikidata direct claims where applicable. URI values in resource pages link back into `/resolve?iri=...` so browsing stays inside the local app; if a browser request cannot be resolved locally, the app opens the original IRI in a new tab as a fallback. `h5tbx serve` accepts files and folders; folder discovery uses `.h5`, `.hdf`, and `.hdf5` by default, or repeated `--h5ext` values. `--local-iri-pattern` is optional and only limits which external IRIs get local resolver links in the graph view. If no filename is provided, `h5tbx serve` lists all matching HDF5 files in the current directory.
|
|
260
|
+
|
|
261
|
+
The same graph metrics are available from Python:
|
|
243
262
|
|
|
244
|
-
|
|
263
|
+
```python
|
|
264
|
+
import h5rdmtoolbox as h5tbx
|
|
245
265
|
|
|
246
|
-
|
|
266
|
+
metrics = h5tbx.compute_metrics("example.h5")
|
|
247
267
|
|
|
268
|
+
with h5tbx.File("example.h5") as h5:
|
|
269
|
+
metrics = h5.metrics()
|
|
270
|
+
```
|
|
248
271
|
|
|
249
272
|
## 🚀 Key Features
|
|
250
273
|
|
|
@@ -151,18 +151,37 @@ hdf:H5T_INTEL_I64 a hdf:Datatype .
|
|
|
151
151
|
hdf:size 4 .
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
## Command Line Interface
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
The `h5tbx` command provides quick access to linked-data serialization and local inspection from the shell.
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
Use `h5tbx ld dump example.h5` to print Turtle RDF, or write a specific format with:
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
```bash
|
|
161
|
+
h5tbx ld dump example.h5 -o example.jsonld
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The dump command accepts `--format`, `--file-uri`, `--prefix`, `--structural=false`, and `--contextual=false`, so you can choose RDF output, assign stable RDF subject URIs, bind a compact prefix, and include only structural or user-provided contextual metadata when needed.
|
|
165
|
+
|
|
166
|
+
To inspect files in a browser, run:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
h5tbx serve example.h5
|
|
170
|
+
h5tbx serve data/ --h5ext=.h5 --h5ext=.hdf5
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The local web app links to Turtle, JSON-LD, N-Triples, RDF/XML, an interactive graph view, SPARQL query editor, graph metrics, and SHACL validation. Per-file buttons are scoped to that file; the landing page also offers a separate combined graph section for all served files plus loaded enrichment. Combined graph visualization is reduced by default with node/edge limits and search controls, and combined metrics skip exact largest-distance computation on very large graphs to keep the local server responsive. HDF5 object URLs such as `/example.h5/group/dataset` dereference to a browser HTML page by default, while `Accept: text/turtle`, `Accept: application/ld+json`, or `?format=ttl|jsonld|nt|xml|html` return the requested representation. For published DOI-style file URIs, use `/resolve?iri=https://doi.org/...%23path` to resolve an exact external RDF subject locally. The resolver uses the first matching served HDF5 subject, caches all served files in one shared query graph, and enriches that graph with known ontology TTL sources, QUDT unit definitions, Zenodo RDF attachments, generic ontology documents, and Wikidata direct claims where applicable. URI values in resource pages link back into `/resolve?iri=...` so browsing stays inside the local app; if a browser request cannot be resolved locally, the app opens the original IRI in a new tab as a fallback. `h5tbx serve` accepts files and folders; folder discovery uses `.h5`, `.hdf`, and `.hdf5` by default, or repeated `--h5ext` values. `--local-iri-pattern` is optional and only limits which external IRIs get local resolver links in the graph view. If no filename is provided, `h5tbx serve` lists all matching HDF5 files in the current directory.
|
|
174
|
+
|
|
175
|
+
The same graph metrics are available from Python:
|
|
161
176
|
|
|
162
|
-
|
|
177
|
+
```python
|
|
178
|
+
import h5rdmtoolbox as h5tbx
|
|
163
179
|
|
|
164
|
-
|
|
180
|
+
metrics = h5tbx.compute_metrics("example.h5")
|
|
165
181
|
|
|
182
|
+
with h5tbx.File("example.h5") as h5:
|
|
183
|
+
metrics = h5.metrics()
|
|
184
|
+
```
|
|
166
185
|
|
|
167
186
|
## 🚀 Key Features
|
|
168
187
|
|
|
@@ -19,7 +19,7 @@ _stream_handler = logging.StreamHandler()
|
|
|
19
19
|
_stream_handler.setLevel(DEFAULT_LOGGING_LEVEL)
|
|
20
20
|
_stream_handler.setFormatter(_formatter)
|
|
21
21
|
|
|
22
|
-
_file_handler = RotatingFileHandler(USER_LOG_DIR / 'h5rdmtoolbox.log')
|
|
22
|
+
_file_handler = RotatingFileHandler(USER_LOG_DIR / 'h5rdmtoolbox.log', delay=True)
|
|
23
23
|
_file_handler.setLevel(logging.DEBUG) # log everything to file!
|
|
24
24
|
_file_handler.setFormatter(_formatter)
|
|
25
25
|
|
|
@@ -146,6 +146,28 @@ def get_ld(
|
|
|
146
146
|
)
|
|
147
147
|
|
|
148
148
|
|
|
149
|
+
def compute_metrics(
|
|
150
|
+
hdf_filename: Union[str, pathlib.Path],
|
|
151
|
+
structural: bool = True,
|
|
152
|
+
contextual: bool = True,
|
|
153
|
+
skipND: int = 1,
|
|
154
|
+
file_uri: Optional[str] = None,
|
|
155
|
+
context: Optional[Dict] = None,
|
|
156
|
+
rdf_mappings: Dict[str, RDFMappingEntry] = None,
|
|
157
|
+
) -> Dict[str, object]:
|
|
158
|
+
"""Compute RDF knowledge graph metrics for an HDF5 file."""
|
|
159
|
+
from .ld.metrics import compute_metrics as _compute_metrics
|
|
160
|
+
return _compute_metrics(
|
|
161
|
+
hdf_filename,
|
|
162
|
+
structural=structural,
|
|
163
|
+
contextual=contextual,
|
|
164
|
+
skipND=skipND,
|
|
165
|
+
file_uri=file_uri,
|
|
166
|
+
context=context,
|
|
167
|
+
rdf_mappings=rdf_mappings,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
149
171
|
def _optimize_ld_context(graph: rdflib.Graph, context: Optional[Dict]) -> Dict:
|
|
150
172
|
from .ld import optimize_context
|
|
151
173
|
return optimize_context(graph, context or {})
|
|
@@ -12,7 +12,7 @@ from .utils import optimize_context
|
|
|
12
12
|
|
|
13
13
|
BINARY_AS_STRING = True
|
|
14
14
|
|
|
15
|
-
__all__ = ["get_ld", "hdf2jsonld", "hdf2ttl", "sparql"]
|
|
15
|
+
__all__ = ["get_ld", "hdf2jsonld", "hdf2ttl", "sparql", "compute_metrics", "compute_graph_metrics"]
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def _validate_file_uri(file_uri: Optional[str]) -> None:
|
|
@@ -280,3 +280,6 @@ def _hdf2ld(
|
|
|
280
280
|
f.write(_serialize_graph(graph, fmt=fmt, indent=indent, context=context))
|
|
281
281
|
|
|
282
282
|
return metadata_filename
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
from .metrics import compute_graph_metrics, compute_metrics # noqa: E402
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Knowledge graph metrics for RDF extracted from HDF5 files."""
|
|
2
|
+
|
|
3
|
+
import pathlib
|
|
4
|
+
import re
|
|
5
|
+
from typing import Dict, Optional, Union
|
|
6
|
+
|
|
7
|
+
import rdflib
|
|
8
|
+
|
|
9
|
+
from . import get_ld
|
|
10
|
+
|
|
11
|
+
STANDARD_PREFIXES = {
|
|
12
|
+
"dcat": "http://www.w3.org/ns/dcat#",
|
|
13
|
+
"dcterms": "http://purl.org/dc/terms/",
|
|
14
|
+
"doi": "https://doi.org/",
|
|
15
|
+
"foaf": "http://xmlns.com/foaf/0.1/",
|
|
16
|
+
"prof": "http://www.w3.org/ns/dx/prof/",
|
|
17
|
+
"prov": "http://www.w3.org/ns/prov#",
|
|
18
|
+
"qudt": "http://qudt.org/schema/qudt/",
|
|
19
|
+
"quantitykind": "http://qudt.org/vocab/quantitykind/",
|
|
20
|
+
"schema": "https://schema.org/",
|
|
21
|
+
"skos": "http://www.w3.org/2004/02/skos/core#",
|
|
22
|
+
"ssno": "https://matthiasprobst.github.io/ssno#",
|
|
23
|
+
"unit": "http://qudt.org/vocab/unit/",
|
|
24
|
+
"zenodo": "https://zenodo.org/records/",
|
|
25
|
+
"zenodo_record": "https://zenodo.org/record/",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def bind_standard_prefixes(graph: rdflib.Graph) -> None:
|
|
30
|
+
"""Bind common namespaces without replacing prefixes already defined by the graph."""
|
|
31
|
+
for prefix, namespace in STANDARD_PREFIXES.items():
|
|
32
|
+
graph.bind(prefix, rdflib.Namespace(namespace), override=False, replace=False)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def graph_label(value, rdf_graph: Optional[rdflib.Graph] = None) -> str:
|
|
36
|
+
"""Return a compact display label for an RDF term."""
|
|
37
|
+
if isinstance(value, rdflib.URIRef):
|
|
38
|
+
namespace_manager = rdf_graph.namespace_manager if rdf_graph is not None else rdflib.Graph().namespace_manager
|
|
39
|
+
text = str(value)
|
|
40
|
+
try:
|
|
41
|
+
normalized = str(namespace_manager.normalizeUri(value))
|
|
42
|
+
if not normalized.startswith("<") and not re.match(r"^ns\d+:", normalized):
|
|
43
|
+
return normalized
|
|
44
|
+
except Exception:
|
|
45
|
+
pass
|
|
46
|
+
for prefix, namespace in STANDARD_PREFIXES.items():
|
|
47
|
+
if text.startswith(namespace) and text != namespace:
|
|
48
|
+
return f"{prefix}:{text[len(namespace):]}"
|
|
49
|
+
try:
|
|
50
|
+
return namespace_manager.qname(value)
|
|
51
|
+
except Exception:
|
|
52
|
+
pass
|
|
53
|
+
if rdf_graph is not None:
|
|
54
|
+
namespaces = sorted(
|
|
55
|
+
((prefix, str(namespace)) for prefix, namespace in rdf_graph.namespaces() if prefix),
|
|
56
|
+
key=lambda item: len(item[1]),
|
|
57
|
+
reverse=True,
|
|
58
|
+
)
|
|
59
|
+
for prefix, namespace in namespaces:
|
|
60
|
+
if text.startswith(namespace) and text != namespace:
|
|
61
|
+
return f"{prefix}:{text[len(namespace):]}"
|
|
62
|
+
return text.rsplit("#", 1)[-1].rsplit("/", 1)[-1] or text
|
|
63
|
+
text = str(value)
|
|
64
|
+
return text if len(text) <= 48 else f"{text[:45]}..."
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _percent(numerator: int, denominator: int) -> float:
|
|
68
|
+
return (numerator / denominator * 100.0) if denominator else 0.0
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _external_namespace(value) -> str:
|
|
72
|
+
text = str(value)
|
|
73
|
+
if "#" in text:
|
|
74
|
+
return text.rsplit("#", 1)[0] + "#"
|
|
75
|
+
if "/" in text:
|
|
76
|
+
return text.rsplit("/", 1)[0] + "/"
|
|
77
|
+
return text
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _resource_terms(subject, predicate, obj) -> list:
|
|
81
|
+
return [
|
|
82
|
+
term
|
|
83
|
+
for term in (subject, predicate, obj)
|
|
84
|
+
if isinstance(term, (rdflib.URIRef, rdflib.BNode))
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def compute_graph_metrics(
|
|
89
|
+
rdf_graph: rdflib.Graph,
|
|
90
|
+
base_namespace: Optional[str] = None,
|
|
91
|
+
compute_distances: bool = True,
|
|
92
|
+
distance_node_limit: int = 2000,
|
|
93
|
+
) -> Dict[str, object]:
|
|
94
|
+
"""Compute RDF knowledge graph metrics for an existing graph."""
|
|
95
|
+
bind_standard_prefixes(rdf_graph)
|
|
96
|
+
triples = list(rdf_graph)
|
|
97
|
+
subjects = set()
|
|
98
|
+
objects = set()
|
|
99
|
+
predicates = set()
|
|
100
|
+
iris = set()
|
|
101
|
+
blank_nodes = set()
|
|
102
|
+
resource_nodes = set()
|
|
103
|
+
literal_count = 0
|
|
104
|
+
untyped_literal_count = 0
|
|
105
|
+
empty_literal_count = 0
|
|
106
|
+
predicate_counts = {}
|
|
107
|
+
subject_triple_counts = {}
|
|
108
|
+
class_instances = {}
|
|
109
|
+
datatype_counts = {}
|
|
110
|
+
language_counts = {}
|
|
111
|
+
labels = set()
|
|
112
|
+
typed_subjects = set()
|
|
113
|
+
same_as_count = 0
|
|
114
|
+
external_iri_counts = {}
|
|
115
|
+
out_degree = {}
|
|
116
|
+
in_degree = {}
|
|
117
|
+
adjacency = {}
|
|
118
|
+
|
|
119
|
+
for subject, predicate, obj in triples:
|
|
120
|
+
subjects.add(subject)
|
|
121
|
+
predicates.add(predicate)
|
|
122
|
+
objects.add(obj)
|
|
123
|
+
subject_triple_counts[subject] = subject_triple_counts.get(subject, 0) + 1
|
|
124
|
+
|
|
125
|
+
for term in _resource_terms(subject, predicate, obj):
|
|
126
|
+
if isinstance(term, rdflib.URIRef):
|
|
127
|
+
iris.add(term)
|
|
128
|
+
namespace = _external_namespace(term)
|
|
129
|
+
if not base_namespace or not str(term).startswith(base_namespace):
|
|
130
|
+
external_iri_counts[namespace] = external_iri_counts.get(namespace, 0) + 1
|
|
131
|
+
elif isinstance(term, rdflib.BNode):
|
|
132
|
+
blank_nodes.add(term)
|
|
133
|
+
|
|
134
|
+
predicate_label = graph_label(predicate, rdf_graph)
|
|
135
|
+
predicate_counts[predicate_label] = predicate_counts.get(predicate_label, 0) + 1
|
|
136
|
+
|
|
137
|
+
if predicate == rdflib.RDF.type:
|
|
138
|
+
typed_subjects.add(subject)
|
|
139
|
+
class_label = graph_label(obj, rdf_graph)
|
|
140
|
+
class_instances.setdefault(class_label, set()).add(subject)
|
|
141
|
+
|
|
142
|
+
if predicate == rdflib.RDFS.label:
|
|
143
|
+
labels.add(subject)
|
|
144
|
+
|
|
145
|
+
if predicate == rdflib.OWL.sameAs:
|
|
146
|
+
same_as_count += 1
|
|
147
|
+
|
|
148
|
+
resource_nodes.add(subject)
|
|
149
|
+
|
|
150
|
+
if isinstance(obj, rdflib.Literal):
|
|
151
|
+
literal_count += 1
|
|
152
|
+
datatype_label = graph_label(obj.datatype, rdf_graph) if obj.datatype else "None"
|
|
153
|
+
datatype_counts[datatype_label] = datatype_counts.get(datatype_label, 0) + 1
|
|
154
|
+
language_label = obj.language or "None"
|
|
155
|
+
language_counts[language_label] = language_counts.get(language_label, 0) + 1
|
|
156
|
+
if obj.datatype is None and obj.language is None:
|
|
157
|
+
untyped_literal_count += 1
|
|
158
|
+
if str(obj) == "":
|
|
159
|
+
empty_literal_count += 1
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
resource_nodes.add(obj)
|
|
163
|
+
out_degree[subject] = out_degree.get(subject, 0) + 1
|
|
164
|
+
in_degree[obj] = in_degree.get(obj, 0) + 1
|
|
165
|
+
adjacency.setdefault(subject, set()).add(obj)
|
|
166
|
+
adjacency.setdefault(obj, set()).add(subject)
|
|
167
|
+
|
|
168
|
+
seen = set()
|
|
169
|
+
component_sizes = []
|
|
170
|
+
for node in resource_nodes:
|
|
171
|
+
if node in seen:
|
|
172
|
+
continue
|
|
173
|
+
stack = [node]
|
|
174
|
+
seen.add(node)
|
|
175
|
+
size = 0
|
|
176
|
+
while stack:
|
|
177
|
+
current = stack.pop()
|
|
178
|
+
size += 1
|
|
179
|
+
for neighbor in adjacency.get(current, set()):
|
|
180
|
+
if neighbor not in seen:
|
|
181
|
+
seen.add(neighbor)
|
|
182
|
+
stack.append(neighbor)
|
|
183
|
+
component_sizes.append(size)
|
|
184
|
+
|
|
185
|
+
resource_count = len(resource_nodes)
|
|
186
|
+
largest_distance = None
|
|
187
|
+
largest_distance_computed = compute_distances and resource_count <= distance_node_limit
|
|
188
|
+
if largest_distance_computed:
|
|
189
|
+
largest_distance = 0
|
|
190
|
+
for start in resource_nodes:
|
|
191
|
+
distances = {start: 0}
|
|
192
|
+
queue = [start]
|
|
193
|
+
for current in queue:
|
|
194
|
+
for neighbor in adjacency.get(current, set()):
|
|
195
|
+
if neighbor not in distances:
|
|
196
|
+
distances[neighbor] = distances[current] + 1
|
|
197
|
+
queue.append(neighbor)
|
|
198
|
+
if distances:
|
|
199
|
+
largest_distance = max(largest_distance, max(distances.values()))
|
|
200
|
+
|
|
201
|
+
subjects_without_type = len(subjects - typed_subjects)
|
|
202
|
+
subjects_with_labels = len(labels)
|
|
203
|
+
subjects_missing_labels = len(subjects - labels)
|
|
204
|
+
duplicate_triples = len(triples) - len(set(triples))
|
|
205
|
+
subjects_with_one_triple = sum(1 for count in subject_triple_counts.values() if count == 1)
|
|
206
|
+
weakly_connected_nodes = sum(
|
|
207
|
+
1 for node in resource_nodes
|
|
208
|
+
if in_degree.get(node, 0) + out_degree.get(node, 0) <= 1
|
|
209
|
+
)
|
|
210
|
+
class_counts = {label: len(instances) for label, instances in class_instances.items()}
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
"triples": len(triples),
|
|
214
|
+
"subjects": len(subjects),
|
|
215
|
+
"predicates": len(predicates),
|
|
216
|
+
"objects": len(objects),
|
|
217
|
+
"iri_count": len(iris),
|
|
218
|
+
"blank_nodes": len(blank_nodes),
|
|
219
|
+
"literals": literal_count,
|
|
220
|
+
"avg_triples_per_subject": len(triples) / len(subjects) if subjects else 0.0,
|
|
221
|
+
"classes": len(class_counts),
|
|
222
|
+
"subjects_without_type": subjects_without_type,
|
|
223
|
+
"resource_nodes": resource_count,
|
|
224
|
+
"avg_out_degree": sum(out_degree.values()) / resource_count if resource_count else 0.0,
|
|
225
|
+
"avg_in_degree": sum(in_degree.values()) / resource_count if resource_count else 0.0,
|
|
226
|
+
"weakly_connected_nodes": weakly_connected_nodes,
|
|
227
|
+
"components": len(component_sizes),
|
|
228
|
+
"largest_component": max(component_sizes, default=0),
|
|
229
|
+
"largest_distance": largest_distance,
|
|
230
|
+
"largest_distance_computed": largest_distance_computed,
|
|
231
|
+
"largest_distance_node_limit": distance_node_limit,
|
|
232
|
+
"datatype_distribution": sorted(datatype_counts.items(), key=lambda item: (-item[1], item[0])),
|
|
233
|
+
"language_distribution": sorted(language_counts.items(), key=lambda item: (-item[1], item[0])),
|
|
234
|
+
"untyped_literals": untyped_literal_count,
|
|
235
|
+
"empty_literals": empty_literal_count,
|
|
236
|
+
"subjects_with_labels": subjects_with_labels,
|
|
237
|
+
"subjects_missing_labels": subjects_missing_labels,
|
|
238
|
+
"label_coverage": _percent(subjects_with_labels, len(subjects)),
|
|
239
|
+
"duplicate_triples": duplicate_triples,
|
|
240
|
+
"subjects_with_one_triple": subjects_with_one_triple,
|
|
241
|
+
"blank_node_percentage": _percent(len(blank_nodes), resource_count),
|
|
242
|
+
"same_as_count": same_as_count,
|
|
243
|
+
"external_iri_count": sum(external_iri_counts.values()),
|
|
244
|
+
"top_external_namespaces": sorted(external_iri_counts.items(), key=lambda item: (-item[1], item[0]))[:10],
|
|
245
|
+
"top_predicates": sorted(predicate_counts.items(), key=lambda item: (-item[1], item[0]))[:10],
|
|
246
|
+
"rare_predicates": sorted(predicate_counts.items(), key=lambda item: (item[1], item[0]))[:10],
|
|
247
|
+
"predicate_distribution": sorted(predicate_counts.items(), key=lambda item: (-item[1], item[0])),
|
|
248
|
+
"top_classes": sorted(class_counts.items(), key=lambda item: (-item[1], item[0]))[:10],
|
|
249
|
+
"top_out_degree": [
|
|
250
|
+
(graph_label(node, rdf_graph), count)
|
|
251
|
+
for node, count in sorted(out_degree.items(), key=lambda item: (-item[1], graph_label(item[0], rdf_graph)))[:10]
|
|
252
|
+
],
|
|
253
|
+
"top_in_degree": [
|
|
254
|
+
(graph_label(node, rdf_graph), count)
|
|
255
|
+
for node, count in sorted(in_degree.items(), key=lambda item: (-item[1], graph_label(item[0], rdf_graph)))[:10]
|
|
256
|
+
],
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def compute_metrics(
|
|
261
|
+
hdf_filename: Union[str, pathlib.Path],
|
|
262
|
+
structural: bool = True,
|
|
263
|
+
contextual: bool = True,
|
|
264
|
+
file_uri: Optional[str] = None,
|
|
265
|
+
skipND: Optional[int] = 1,
|
|
266
|
+
context: Optional[Dict] = None,
|
|
267
|
+
rdf_mappings: Optional[Dict] = None,
|
|
268
|
+
) -> Dict[str, object]:
|
|
269
|
+
"""Compute RDF knowledge graph metrics for an HDF5 file."""
|
|
270
|
+
graph = get_ld(
|
|
271
|
+
hdf_filename,
|
|
272
|
+
structural=structural,
|
|
273
|
+
contextual=contextual,
|
|
274
|
+
file_uri=file_uri,
|
|
275
|
+
skipND=skipND,
|
|
276
|
+
context=context,
|
|
277
|
+
rdf_mappings=rdf_mappings,
|
|
278
|
+
)
|
|
279
|
+
return compute_graph_metrics(graph, base_namespace=file_uri)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""LLM-based chat support for HDF5 metadata graphs."""
|
|
2
|
+
|
|
3
|
+
from .chat import chat
|
|
4
|
+
from .models import ChatResponse, ChatSession, ChatSessionState, QueryAttempt
|
|
5
|
+
from .providers.openai_adapter import OpenAIChatClient
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"chat",
|
|
9
|
+
"ChatResponse",
|
|
10
|
+
"ChatSession",
|
|
11
|
+
"ChatSessionState",
|
|
12
|
+
"QueryAttempt",
|
|
13
|
+
"OpenAIChatClient",
|
|
14
|
+
]
|
|
15
|
+
|