semantic-benchmark 0.4.2__tar.gz → 0.4.4__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.
- {semantic_benchmark-0.4.2/src/semantic_benchmark.egg-info → semantic_benchmark-0.4.4}/PKG-INFO +13 -6
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/README.md +10 -3
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/pyproject.toml +3 -3
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rocrate/create.py +105 -162
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/provenance.py +5 -5
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/runner.py +6 -6
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4/src/semantic_benchmark.egg-info}/PKG-INFO +13 -6
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark.egg-info/requires.txt +2 -2
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/LICENSE +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/setup.cfg +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/__init__.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rocrate/__init__.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rocrate/validation.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/__init__.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/download.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/rohub_config.json +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/upload.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantic.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/__init__.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/loader.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/models.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/benchmark.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/data-source.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/field.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/file-object.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/mathematical-model.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/numerical-variable.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/parameter-set.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/processing-step.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/shapes/research-problem.ttl +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/vocabulary.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark.egg-info/SOURCES.txt +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark.egg-info/dependency_links.txt +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark.egg-info/entry_points.txt +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark.egg-info/top_level.txt +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/tests/test_loader.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/tests/test_published_runs_query.py +0 -0
- {semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/tests/test_upload_match_query.py +0 -0
{semantic_benchmark-0.4.2/src/semantic_benchmark.egg-info → semantic_benchmark-0.4.4}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: semantic-benchmark
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
4
4
|
Summary: Reusable helpers for semantic benchmark metadata, RO-Crate aggregation, and RoHub provenance workflows.
|
|
5
5
|
Author-email: Mahdi Jafarkhani <mahdi.jafarkhani@tik.uni-stuttgart.de>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -28,9 +28,9 @@ Provides-Extra: test
|
|
|
28
28
|
Requires-Dist: pytest; extra == "test"
|
|
29
29
|
Provides-Extra: rocrate
|
|
30
30
|
Requires-Dist: rocrate; extra == "rocrate"
|
|
31
|
-
Requires-Dist: roc-validator; extra == "rocrate"
|
|
31
|
+
Requires-Dist: roc-validator==0.12.2; extra == "rocrate"
|
|
32
32
|
Provides-Extra: all
|
|
33
|
-
Requires-Dist: roc-validator; extra == "all"
|
|
33
|
+
Requires-Dist: roc-validator==0.12.2; extra == "all"
|
|
34
34
|
Requires-Dist: rocrate; extra == "all"
|
|
35
35
|
Dynamic: license-file
|
|
36
36
|
|
|
@@ -96,11 +96,18 @@ It accepts `--provenance_folderpath` (the RO-Crate ZIP), `--benchmark-name`,
|
|
|
96
96
|
`--use-production-rohub` arguments. The software URL and version are read from
|
|
97
97
|
the SoftwareApplication node in the RO-Crate ZIP.
|
|
98
98
|
|
|
99
|
-
`semantic_benchmark.rocrate.create_main_ro(...)`
|
|
100
|
-
aggregate crate
|
|
99
|
+
`semantic_benchmark.rocrate.create_main_ro(...)` always validates the generated
|
|
100
|
+
aggregate crate against `workflow-run-crate-0.5`. The package writes the RO-Crate
|
|
101
101
|
zip, unpacks it to a validation directory, and runs `validate_rocrate(...)`.
|
|
102
102
|
Aggregate creation requires `subcrate_paths`, the exact reporter RO-Crate ZIPs
|
|
103
|
-
from completed runs
|
|
103
|
+
from completed runs, and `workflow_path`, a YAML file used as the main workflow.
|
|
104
|
+
The CLI accepts `--workflow-path` and one `--subcrate-path` per run. Each subcrate
|
|
105
|
+
is the result of a `CreateAction` whose instrument is the YAML workflow; matched
|
|
106
|
+
configuration values are action inputs and extracted metrics are action results.
|
|
107
|
+
Pass `agent_name` and `agent_orcid` from the reporter configuration's
|
|
108
|
+
`report-rocrate-agent-name` and `report-rocrate-agent-orcid` values. They identify
|
|
109
|
+
the workflow author and creator in the aggregate crate. The CLI accepts
|
|
110
|
+
`--agent-name` and `--agent-orcid`.
|
|
104
111
|
|
|
105
112
|
Repository-specific projects can override the packaged RoHub defaults with:
|
|
106
113
|
|
|
@@ -60,11 +60,18 @@ It accepts `--provenance_folderpath` (the RO-Crate ZIP), `--benchmark-name`,
|
|
|
60
60
|
`--use-production-rohub` arguments. The software URL and version are read from
|
|
61
61
|
the SoftwareApplication node in the RO-Crate ZIP.
|
|
62
62
|
|
|
63
|
-
`semantic_benchmark.rocrate.create_main_ro(...)`
|
|
64
|
-
aggregate crate
|
|
63
|
+
`semantic_benchmark.rocrate.create_main_ro(...)` always validates the generated
|
|
64
|
+
aggregate crate against `workflow-run-crate-0.5`. The package writes the RO-Crate
|
|
65
65
|
zip, unpacks it to a validation directory, and runs `validate_rocrate(...)`.
|
|
66
66
|
Aggregate creation requires `subcrate_paths`, the exact reporter RO-Crate ZIPs
|
|
67
|
-
from completed runs
|
|
67
|
+
from completed runs, and `workflow_path`, a YAML file used as the main workflow.
|
|
68
|
+
The CLI accepts `--workflow-path` and one `--subcrate-path` per run. Each subcrate
|
|
69
|
+
is the result of a `CreateAction` whose instrument is the YAML workflow; matched
|
|
70
|
+
configuration values are action inputs and extracted metrics are action results.
|
|
71
|
+
Pass `agent_name` and `agent_orcid` from the reporter configuration's
|
|
72
|
+
`report-rocrate-agent-name` and `report-rocrate-agent-orcid` values. They identify
|
|
73
|
+
the workflow author and creator in the aggregate crate. The CLI accepts
|
|
74
|
+
`--agent-name` and `--agent-orcid`.
|
|
68
75
|
|
|
69
76
|
Repository-specific projects can override the packaged RoHub defaults with:
|
|
70
77
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "semantic-benchmark"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.4"
|
|
8
8
|
description = "Reusable helpers for semantic benchmark metadata, RO-Crate aggregation, and RoHub provenance workflows."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -38,10 +38,10 @@ test = [
|
|
|
38
38
|
]
|
|
39
39
|
rocrate = [
|
|
40
40
|
"rocrate",
|
|
41
|
-
"roc-validator",
|
|
41
|
+
"roc-validator==0.12.2",
|
|
42
42
|
]
|
|
43
43
|
all = [
|
|
44
|
-
"roc-validator",
|
|
44
|
+
"roc-validator==0.12.2",
|
|
45
45
|
"rocrate",
|
|
46
46
|
]
|
|
47
47
|
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rocrate/create.py
RENAMED
|
@@ -6,13 +6,13 @@ import argparse
|
|
|
6
6
|
import json
|
|
7
7
|
import logging
|
|
8
8
|
import re
|
|
9
|
-
import shutil
|
|
10
9
|
import tempfile
|
|
11
10
|
import uuid
|
|
12
11
|
import zipfile
|
|
13
12
|
from pathlib import Path
|
|
14
|
-
from typing import Any,
|
|
13
|
+
from typing import Any, TypedDict
|
|
15
14
|
|
|
15
|
+
from rocrate.model.computationalworkflow import ComputationalWorkflow
|
|
16
16
|
from rocrate.model.softwareapplication import SoftwareApplication
|
|
17
17
|
from rocrate.rocrate import ROCrate
|
|
18
18
|
from semantic_benchmark import semantics
|
|
@@ -21,42 +21,33 @@ from semantic_benchmark.rocrate.validation import validate_rocrate
|
|
|
21
21
|
LOG_FORMAT = "%(levelname)s:%(name)s:%(message)s"
|
|
22
22
|
LOGGER = logging.getLogger(__name__)
|
|
23
23
|
|
|
24
|
-
WorkflowLanguage = Literal["nextflow", "snakemake"]
|
|
25
|
-
|
|
26
24
|
ROCRATE_CONFORMS_TO = [
|
|
27
25
|
{"@id": "https://w3id.org/ro/crate/1.1"},
|
|
28
|
-
{"@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.0"},
|
|
29
26
|
]
|
|
30
27
|
ROOT_DATASET_CONFORMS_TO = [
|
|
31
|
-
{"@id": "https://w3id.org/ro/wfrun/process/0.
|
|
32
|
-
{"@id": "https://w3id.org/ro/wfrun/workflow/0.
|
|
33
|
-
{"@id": "https://w3id.org/ro/
|
|
34
|
-
{"@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.0"},
|
|
28
|
+
{"@id": "https://w3id.org/ro/wfrun/process/0.6"},
|
|
29
|
+
{"@id": "https://w3id.org/ro/wfrun/workflow/0.6"},
|
|
30
|
+
{"@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.1"},
|
|
35
31
|
]
|
|
32
|
+
AGGREGATE_VALIDATION_PROFILE = "workflow-run-crate-0.5"
|
|
36
33
|
PROFILE_CREATIVE_WORKS = (
|
|
37
34
|
{
|
|
38
|
-
"@id": "https://w3id.org/ro/wfrun/process/0.
|
|
35
|
+
"@id": "https://w3id.org/ro/wfrun/process/0.6",
|
|
39
36
|
"@type": "CreativeWork",
|
|
40
37
|
"name": "Process Run Crate",
|
|
41
|
-
"version": "0.
|
|
38
|
+
"version": "0.6",
|
|
42
39
|
},
|
|
43
40
|
{
|
|
44
|
-
"@id": "https://w3id.org/ro/wfrun/workflow/0.
|
|
41
|
+
"@id": "https://w3id.org/ro/wfrun/workflow/0.6",
|
|
45
42
|
"@type": "CreativeWork",
|
|
46
43
|
"name": "Workflow Run Crate",
|
|
47
|
-
"version": "0.
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"@id": "https://w3id.org/ro/wfrun/provenance/0.4",
|
|
51
|
-
"@type": "CreativeWork",
|
|
52
|
-
"name": "Provenance Run Crate",
|
|
53
|
-
"version": "0.4",
|
|
44
|
+
"version": "0.6",
|
|
54
45
|
},
|
|
55
46
|
{
|
|
56
|
-
"@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.
|
|
47
|
+
"@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.1",
|
|
57
48
|
"@type": "CreativeWork",
|
|
58
49
|
"name": "Workflow RO-Crate",
|
|
59
|
-
"version": "1.
|
|
50
|
+
"version": "1.1",
|
|
60
51
|
},
|
|
61
52
|
)
|
|
62
53
|
|
|
@@ -150,23 +141,6 @@ def _add_subcrates_to_main(
|
|
|
150
141
|
)
|
|
151
142
|
|
|
152
143
|
|
|
153
|
-
def _create_action_object_ids(input_path: Path, subcrates: list[Path]) -> dict[str, str]:
|
|
154
|
-
"""Map run folder names to relative subcrate object ids.
|
|
155
|
-
|
|
156
|
-
Args:
|
|
157
|
-
input_path: Root simulation result directory.
|
|
158
|
-
subcrates: Reporter RO-Crate ZIPs for completed runs.
|
|
159
|
-
|
|
160
|
-
Returns:
|
|
161
|
-
Mapping from run folder name to the subcrate ZIP path relative to
|
|
162
|
-
``input_path``.
|
|
163
|
-
"""
|
|
164
|
-
object_ids: dict[str, str] = {}
|
|
165
|
-
for subcrate in subcrates:
|
|
166
|
-
object_ids.setdefault(subcrate.parent.name, str(subcrate.relative_to(input_path)))
|
|
167
|
-
return object_ids
|
|
168
|
-
|
|
169
|
-
|
|
170
144
|
def _formal_parameter_key(part: semantics.ParameterEntry) -> tuple[Any, ...]:
|
|
171
145
|
"""Build a stable de-duplication key for a benchmark parameter.
|
|
172
146
|
|
|
@@ -205,15 +179,17 @@ def _formal_parameter_payload(
|
|
|
205
179
|
}
|
|
206
180
|
|
|
207
181
|
unit = getattr(part, "unit", None)
|
|
208
|
-
payload["additionalType"] =
|
|
182
|
+
payload["additionalType"] = (
|
|
183
|
+
"Float" if isinstance(part, (semantics.NumericalParameter, semantics.NumericalVariable)) else "Text"
|
|
184
|
+
)
|
|
209
185
|
|
|
210
186
|
if unit is not None:
|
|
211
187
|
payload["unitText"] = {"@id": unit}
|
|
212
188
|
|
|
213
189
|
if isinstance(part, semantics.NumericalParameter):
|
|
214
|
-
payload["
|
|
190
|
+
payload["value"] = part.numerical_value
|
|
215
191
|
elif isinstance(part, semantics.TextParameter):
|
|
216
|
-
payload["
|
|
192
|
+
payload["value"] = part.string_value
|
|
217
193
|
elif (
|
|
218
194
|
isinstance(part, semantics.NumericalVariable)
|
|
219
195
|
and part.quantity_kind is not None
|
|
@@ -515,10 +491,10 @@ def _metric_result_payload(
|
|
|
515
491
|
"@id": result_id,
|
|
516
492
|
"@type": "PropertyValue",
|
|
517
493
|
"name": metric.label,
|
|
518
|
-
"
|
|
494
|
+
"value": value,
|
|
519
495
|
}
|
|
520
496
|
if metric.unit:
|
|
521
|
-
payload["
|
|
497
|
+
payload["unitText"] = {"@id": metric.unit}
|
|
522
498
|
return payload
|
|
523
499
|
|
|
524
500
|
|
|
@@ -597,12 +573,12 @@ def _configuration_entries_for_step(
|
|
|
597
573
|
|
|
598
574
|
def _add_run_actions(
|
|
599
575
|
crate: ROCrate,
|
|
600
|
-
|
|
601
|
-
|
|
576
|
+
subcrates: list[Path],
|
|
577
|
+
input_path: Path,
|
|
602
578
|
processing_steps: list[semantics.ProcessingStep],
|
|
603
579
|
configuration_entries: list[ConfigurationEntry],
|
|
604
580
|
run_results_by_name: dict[str, list[dict[str, str]]],
|
|
605
|
-
|
|
581
|
+
workflow_id: str,
|
|
606
582
|
) -> None:
|
|
607
583
|
"""Add run action nodes connecting runs, configurations, and results.
|
|
608
584
|
|
|
@@ -618,14 +594,11 @@ def _add_run_actions(
|
|
|
618
594
|
Returns:
|
|
619
595
|
None. The function mutates ``crate`` by adding ``CreateAction`` nodes.
|
|
620
596
|
"""
|
|
621
|
-
for
|
|
597
|
+
for subcrate in subcrates:
|
|
598
|
+
run_folder = subcrate.parent
|
|
622
599
|
run_name = run_folder.name
|
|
623
|
-
run_object_id = object_ids_by_run.get(run_name)
|
|
624
|
-
if not run_object_id:
|
|
625
|
-
continue
|
|
626
|
-
|
|
627
600
|
result_ids = run_results_by_name.get(run_name, [])
|
|
628
|
-
|
|
601
|
+
object_ids = []
|
|
629
602
|
for processing_step in processing_steps:
|
|
630
603
|
step_configuration_entries = _configuration_entries_for_step(
|
|
631
604
|
configuration_entries, processing_step
|
|
@@ -634,19 +607,20 @@ def _add_run_actions(
|
|
|
634
607
|
run_folder, step_configuration_entries
|
|
635
608
|
)
|
|
636
609
|
|
|
637
|
-
step_name = processing_step.label or processing_step.id
|
|
638
|
-
run_action: dict[str, Any] = {
|
|
639
|
-
"@id": _new_jsonld_id(),
|
|
640
|
-
"@type": "CreateAction",
|
|
641
|
-
"name": f"{step_name} {run_name}",
|
|
642
|
-
"object": [{"@id": run_object_id}],
|
|
643
|
-
"instrument": {"@id": software_id},
|
|
644
|
-
}
|
|
645
610
|
if config_id:
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
611
|
+
object_ids.append({"@id": config_id})
|
|
612
|
+
run_action: dict[str, Any] = {
|
|
613
|
+
"@id": _new_jsonld_id(),
|
|
614
|
+
"@type": "CreateAction",
|
|
615
|
+
"name": f"Benchmark run {run_name}",
|
|
616
|
+
"instrument": {"@id": workflow_id},
|
|
617
|
+
"result": [{"@id": str(subcrate.relative_to(input_path))}, *result_ids],
|
|
618
|
+
}
|
|
619
|
+
if object_ids:
|
|
620
|
+
run_action["object"] = object_ids
|
|
621
|
+
action_id = run_action["@id"]
|
|
622
|
+
crate.add_jsonld(run_action)
|
|
623
|
+
crate.root_dataset.append_to("mentions", {"@id": action_id})
|
|
650
624
|
|
|
651
625
|
|
|
652
626
|
def _configure_crate_metadata(
|
|
@@ -714,33 +688,48 @@ def _add_software_node(
|
|
|
714
688
|
)
|
|
715
689
|
|
|
716
690
|
|
|
691
|
+
def _add_yaml_language_node(crate: ROCrate) -> dict[str, str]:
|
|
692
|
+
"""Add the YAML language node and return its JSON-LD reference."""
|
|
693
|
+
yaml_id = "https://www.wikidata.org/entity/Q281876"
|
|
694
|
+
crate.add_jsonld(
|
|
695
|
+
{
|
|
696
|
+
"@id": yaml_id,
|
|
697
|
+
"@type": "ComputerLanguage",
|
|
698
|
+
"identifier": yaml_id,
|
|
699
|
+
"name": "YAML",
|
|
700
|
+
"url": "https://yaml.org/",
|
|
701
|
+
}
|
|
702
|
+
)
|
|
703
|
+
return {"@id": yaml_id}
|
|
704
|
+
|
|
705
|
+
|
|
717
706
|
def _add_workflow_node(
|
|
718
707
|
crate: ROCrate,
|
|
719
708
|
workflow_path: Path,
|
|
720
709
|
software_id: str,
|
|
721
|
-
|
|
722
|
-
|
|
710
|
+
agent_name: str,
|
|
711
|
+
agent_orcid: str,
|
|
723
712
|
) -> None:
|
|
724
713
|
"""Add the main workflow file to the aggregate crate.
|
|
725
714
|
|
|
726
715
|
Args:
|
|
727
716
|
crate: Aggregate RO-Crate being built.
|
|
728
717
|
workflow_path: Location of the workflow file to add.
|
|
729
|
-
software_id: JSON-LD id of the software application
|
|
730
|
-
|
|
731
|
-
|
|
718
|
+
software_id: JSON-LD id of the software application requirement.
|
|
719
|
+
agent_name: Name of the workflow author and creator.
|
|
720
|
+
agent_orcid: ORCID URL identifying the author and creator.
|
|
732
721
|
|
|
733
722
|
Returns:
|
|
734
723
|
None. The function mutates ``crate``.
|
|
735
724
|
"""
|
|
736
|
-
crate.
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
)
|
|
725
|
+
workflow = crate.add(ComputationalWorkflow(crate, source=str(workflow_path)))
|
|
726
|
+
workflow["encodingFormat"] = "application/yaml"
|
|
727
|
+
workflow["softwareRequirements"] = {"@id": software_id}
|
|
728
|
+
workflow["programmingLanguage"] = _add_yaml_language_node(crate)
|
|
729
|
+
person = {"@id": agent_orcid}
|
|
730
|
+
workflow["author"] = person
|
|
731
|
+
workflow["creator"] = person
|
|
732
|
+
crate.add_jsonld({"@id": agent_orcid, "@type": "Person", "name": agent_name})
|
|
744
733
|
|
|
745
734
|
|
|
746
735
|
def create_main_ro(
|
|
@@ -752,12 +741,11 @@ def create_main_ro(
|
|
|
752
741
|
crate_name: str,
|
|
753
742
|
crate_description: str,
|
|
754
743
|
subcrate_paths: list[str | Path],
|
|
755
|
-
workflow_path: str | Path
|
|
756
|
-
lang: WorkflowLanguage = "snakemake",
|
|
757
|
-
validation_profile: str | None = None,
|
|
758
|
-
validation_dir: str | Path | None = None,
|
|
744
|
+
workflow_path: str | Path = "",
|
|
759
745
|
software_url: str | None = None,
|
|
760
746
|
software_version: str | None = None,
|
|
747
|
+
agent_name: str | None = None,
|
|
748
|
+
agent_orcid: str | None = None,
|
|
761
749
|
) -> None:
|
|
762
750
|
"""Create and write an aggregate RO-Crate for a benchmark result directory.
|
|
763
751
|
|
|
@@ -770,16 +758,12 @@ def create_main_ro(
|
|
|
770
758
|
crate_license: License URL stored on the aggregate RO-Crate.
|
|
771
759
|
crate_name: Human-readable name stored on the aggregate RO-Crate.
|
|
772
760
|
crate_description: Description stored on the aggregate RO-Crate.
|
|
773
|
-
workflow_path:
|
|
774
|
-
to the workflow found alongside the first subcrate.
|
|
775
|
-
lang: Workflow language. Defaults to ``snakemake``.
|
|
776
|
-
validation_profile: Optional RO-Crate profile identifier. When provided,
|
|
777
|
-
the written crate is unpacked and validated against this profile.
|
|
778
|
-
validation_dir: Optional directory used for unpacked validation content.
|
|
779
|
-
Defaults to ``unpacked_rocrate`` next to ``rocrate_path``.
|
|
761
|
+
workflow_path: Required YAML workflow file to add as the main entity.
|
|
780
762
|
software_url: Stable software identifier (for example, a zbMATH URL).
|
|
781
763
|
If omitted, a local identifier is generated.
|
|
782
764
|
software_version: Software version to record, if known.
|
|
765
|
+
agent_name: Name supplied by the reporter configuration.
|
|
766
|
+
agent_orcid: ORCID URL supplied by the reporter configuration.
|
|
783
767
|
subcrate_paths: Exact reporter RO-Crate ZIPs to include.
|
|
784
768
|
|
|
785
769
|
Returns:
|
|
@@ -788,20 +772,23 @@ def create_main_ro(
|
|
|
788
772
|
|
|
789
773
|
Raises:
|
|
790
774
|
NotADirectoryError: If ``path`` is not a directory.
|
|
791
|
-
FileNotFoundError: If the
|
|
792
|
-
ValueError: If
|
|
793
|
-
are found.
|
|
775
|
+
FileNotFoundError: If the workflow path is not a file.
|
|
776
|
+
ValueError: If no matching subcrate zip files are found.
|
|
794
777
|
"""
|
|
795
778
|
crate = ROCrate(version="1.1")
|
|
796
779
|
input_path = Path(path)
|
|
797
780
|
|
|
798
781
|
if not input_path.is_dir():
|
|
799
782
|
raise NotADirectoryError(f"{path} is not a valid directory")
|
|
800
|
-
if
|
|
801
|
-
raise ValueError(
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
783
|
+
if not workflow_path:
|
|
784
|
+
raise ValueError("workflow_path is required")
|
|
785
|
+
if not agent_name or not agent_orcid:
|
|
786
|
+
raise ValueError("agent_name and agent_orcid are required")
|
|
787
|
+
workflow_file = Path(workflow_path).resolve()
|
|
788
|
+
if not workflow_file.is_file():
|
|
789
|
+
raise FileNotFoundError(f"{workflow_file} is not a valid workflow file")
|
|
790
|
+
if workflow_file.suffix.lower() not in {".yaml", ".yml"}:
|
|
791
|
+
raise ValueError("workflow_path must be a YAML file")
|
|
805
792
|
LOGGER.info(
|
|
806
793
|
"Creating aggregate RO-Crate from simulation results in %s...",
|
|
807
794
|
input_path,
|
|
@@ -825,35 +812,23 @@ def create_main_ro(
|
|
|
825
812
|
|
|
826
813
|
_add_subcrates_to_main(crate, subcrates, input_path)
|
|
827
814
|
|
|
828
|
-
object_ids_by_run = _create_action_object_ids(input_path, subcrates)
|
|
829
815
|
configuration_entries = _add_configuration_nodes(crate, benchmark_object)
|
|
830
816
|
run_results = _add_evaluates_nodes(
|
|
831
817
|
crate, benchmark_object, extracted_subfolders
|
|
832
818
|
)
|
|
833
819
|
run_results_by_name = _run_results_by_name(run_results)
|
|
834
820
|
|
|
835
|
-
workflow_id =
|
|
836
|
-
subcrates[0],
|
|
837
|
-
fallback=Path(workflow_path).name if workflow_path is not None else "Snakefile",
|
|
838
|
-
)
|
|
839
|
-
workflow_file = (
|
|
840
|
-
Path(workflow_path)
|
|
841
|
-
if workflow_path is not None
|
|
842
|
-
else extraction_path / subcrates[0].parent.relative_to(input_path) / workflow_id
|
|
843
|
-
)
|
|
844
|
-
if not workflow_file.is_file():
|
|
845
|
-
raise FileNotFoundError(f"{workflow_file} is not a valid workflow file")
|
|
846
|
-
|
|
821
|
+
workflow_id = workflow_file.name
|
|
847
822
|
software_id = software_url or _new_jsonld_id()
|
|
848
823
|
|
|
849
824
|
_add_run_actions(
|
|
850
825
|
crate=crate,
|
|
851
|
-
|
|
852
|
-
|
|
826
|
+
subcrates=subcrates,
|
|
827
|
+
input_path=input_path,
|
|
853
828
|
processing_steps=benchmark_object.processing_steps,
|
|
854
829
|
configuration_entries=configuration_entries,
|
|
855
830
|
run_results_by_name=run_results_by_name,
|
|
856
|
-
|
|
831
|
+
workflow_id=workflow_id,
|
|
857
832
|
)
|
|
858
833
|
_configure_crate_metadata(
|
|
859
834
|
crate,
|
|
@@ -864,28 +839,18 @@ def create_main_ro(
|
|
|
864
839
|
)
|
|
865
840
|
_add_software_node(crate, software_id, software_name, software_version)
|
|
866
841
|
_add_profile_creative_works(crate)
|
|
867
|
-
_add_workflow_node(crate, workflow_file, software_id,
|
|
842
|
+
_add_workflow_node(crate, workflow_file, software_id, agent_name, agent_orcid)
|
|
868
843
|
|
|
869
844
|
crate.write_zip(rocrate_path)
|
|
870
845
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
)
|
|
875
|
-
if validation_path.exists():
|
|
876
|
-
shutil.rmtree(validation_path)
|
|
877
|
-
validation_path.mkdir(parents=True, exist_ok=True)
|
|
878
|
-
|
|
879
|
-
try:
|
|
880
|
-
with zipfile.ZipFile(rocrate_path, "r") as zip_ref:
|
|
881
|
-
zip_ref.extractall(validation_path)
|
|
846
|
+
with tempfile.TemporaryDirectory(prefix="benchmark-validation-") as validation_dir:
|
|
847
|
+
with zipfile.ZipFile(rocrate_path, "r") as zip_ref:
|
|
848
|
+
zip_ref.extractall(validation_dir)
|
|
882
849
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
finally:
|
|
888
|
-
shutil.rmtree(validation_path)
|
|
850
|
+
validate_rocrate(
|
|
851
|
+
rocrate_path=validation_dir,
|
|
852
|
+
profile=AGGREGATE_VALIDATION_PROFILE,
|
|
853
|
+
)
|
|
889
854
|
|
|
890
855
|
|
|
891
856
|
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
@@ -948,30 +913,20 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
|
948
913
|
required=True,
|
|
949
914
|
help="Description recorded in the generated aggregate RO-Crate",
|
|
950
915
|
)
|
|
951
|
-
parser.add_argument(
|
|
952
|
-
"--lang",
|
|
953
|
-
dest="workflow_lang",
|
|
954
|
-
default="snakemake",
|
|
955
|
-
choices=get_args(WorkflowLanguage),
|
|
956
|
-
help="Language of the workflow file (default: snakemake)",
|
|
957
|
-
)
|
|
958
916
|
parser.add_argument(
|
|
959
917
|
"--workflow-path",
|
|
960
|
-
|
|
961
|
-
help=
|
|
962
|
-
"Path to the workflow file added to the generated RO-Crate "
|
|
963
|
-
"(default: workflow alongside the first subcrate)"
|
|
964
|
-
),
|
|
918
|
+
required=True,
|
|
919
|
+
help="Path to the YAML workflow file used as the main entity",
|
|
965
920
|
)
|
|
966
921
|
parser.add_argument(
|
|
967
|
-
"--
|
|
968
|
-
|
|
969
|
-
help="
|
|
922
|
+
"--agent-name",
|
|
923
|
+
required=True,
|
|
924
|
+
help="Workflow author and creator name from report-rocrate-agent-name",
|
|
970
925
|
)
|
|
971
926
|
parser.add_argument(
|
|
972
|
-
"--
|
|
973
|
-
|
|
974
|
-
help="
|
|
927
|
+
"--agent-orcid",
|
|
928
|
+
required=True,
|
|
929
|
+
help="Workflow author and creator ORCID URL from report-rocrate-agent-orcid",
|
|
975
930
|
)
|
|
976
931
|
|
|
977
932
|
return parser.parse_args(argv)
|
|
@@ -999,22 +954,10 @@ def main() -> None:
|
|
|
999
954
|
crate_description=args.crate_description,
|
|
1000
955
|
subcrate_paths=args.subcrate_paths,
|
|
1001
956
|
workflow_path=args.workflow_path,
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
validation_dir=args.validation_dir,
|
|
957
|
+
agent_name=args.agent_name,
|
|
958
|
+
agent_orcid=args.agent_orcid,
|
|
1005
959
|
)
|
|
1006
960
|
|
|
1007
961
|
|
|
1008
|
-
def get_workflow_id(subcrate: str | Path, fallback: str = "Snakefile") -> str:
|
|
1009
|
-
"""Return the computational workflow id stored in a subcrate."""
|
|
1010
|
-
crate = ROCrate(subcrate)
|
|
1011
|
-
|
|
1012
|
-
for e in crate.get_entities():
|
|
1013
|
-
if e.type == ["ComputationalWorkflow"]:
|
|
1014
|
-
return e.id
|
|
1015
|
-
|
|
1016
|
-
return fallback
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
962
|
if __name__ == "__main__":
|
|
1020
963
|
main()
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/provenance.py
RENAMED
|
@@ -194,14 +194,14 @@ def _value_block(
|
|
|
194
194
|
{parent} {relation} ?{node_prefix}_{safe_name} .
|
|
195
195
|
?{node_prefix}_{safe_name} a {_node_type(node_prefix)} ;
|
|
196
196
|
{name_predicate} "{escaped_name}" ;
|
|
197
|
-
schema:defaultValue ?{safe_name} .
|
|
197
|
+
(schema:value|schema:defaultValue) ?{safe_name} .
|
|
198
198
|
""".strip()
|
|
199
199
|
|
|
200
200
|
|
|
201
201
|
def _parameter_block(
|
|
202
202
|
name: str,
|
|
203
203
|
var_map: dict[str, str],
|
|
204
|
-
name_predicate: str =
|
|
204
|
+
name_predicate: str = FOAF_NAME,
|
|
205
205
|
) -> str:
|
|
206
206
|
"""Build a graph pattern that extracts one configuration parameter."""
|
|
207
207
|
return _value_block(
|
|
@@ -217,7 +217,7 @@ def _parameter_block(
|
|
|
217
217
|
def _metric_block(
|
|
218
218
|
name: str,
|
|
219
219
|
var_map: dict[str, str],
|
|
220
|
-
name_predicate: str =
|
|
220
|
+
name_predicate: str = FOAF_NAME,
|
|
221
221
|
) -> str:
|
|
222
222
|
"""Build an optional graph pattern that extracts one run metric."""
|
|
223
223
|
value_block = _value_block(
|
|
@@ -300,9 +300,9 @@ def build_dynamic_query(
|
|
|
300
300
|
inner_query = _join_blocks(
|
|
301
301
|
"\n".join(_create_action_links(include_tool=True)),
|
|
302
302
|
"\n".join(
|
|
303
|
-
_parameter_block(name, var_map
|
|
303
|
+
_parameter_block(name, var_map) for name in parameters
|
|
304
304
|
),
|
|
305
|
-
"\n".join(_metric_block(name, var_map
|
|
305
|
+
"\n".join(_metric_block(name, var_map) for name in metrics),
|
|
306
306
|
)
|
|
307
307
|
|
|
308
308
|
order_name = parameters[0] if parameters else None
|
|
@@ -203,7 +203,9 @@ def create_aggregate_rocrate(
|
|
|
203
203
|
crate_name: str,
|
|
204
204
|
crate_description: str,
|
|
205
205
|
subcrate_paths: list[str | Path],
|
|
206
|
-
|
|
206
|
+
workflow_path: str | Path,
|
|
207
|
+
agent_name: str,
|
|
208
|
+
agent_orcid: str,
|
|
207
209
|
software_url: str | None = None,
|
|
208
210
|
software_version: str | None = None,
|
|
209
211
|
) -> None:
|
|
@@ -212,9 +214,6 @@ def create_aggregate_rocrate(
|
|
|
212
214
|
# the core runner helpers remain available without the ``rocrate`` extra.
|
|
213
215
|
from . import rocrate
|
|
214
216
|
|
|
215
|
-
options = {}
|
|
216
|
-
if validation_dir is not None:
|
|
217
|
-
options["validation_dir"] = validation_dir
|
|
218
217
|
rocrate.create_main_ro(
|
|
219
218
|
path=str(results_dir),
|
|
220
219
|
benchmark_object=benchmark,
|
|
@@ -226,6 +225,7 @@ def create_aggregate_rocrate(
|
|
|
226
225
|
crate_name=crate_name,
|
|
227
226
|
crate_description=crate_description,
|
|
228
227
|
subcrate_paths=subcrate_paths,
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
workflow_path=workflow_path,
|
|
229
|
+
agent_name=agent_name,
|
|
230
|
+
agent_orcid=agent_orcid,
|
|
231
231
|
)
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4/src/semantic_benchmark.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: semantic-benchmark
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
4
4
|
Summary: Reusable helpers for semantic benchmark metadata, RO-Crate aggregation, and RoHub provenance workflows.
|
|
5
5
|
Author-email: Mahdi Jafarkhani <mahdi.jafarkhani@tik.uni-stuttgart.de>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -28,9 +28,9 @@ Provides-Extra: test
|
|
|
28
28
|
Requires-Dist: pytest; extra == "test"
|
|
29
29
|
Provides-Extra: rocrate
|
|
30
30
|
Requires-Dist: rocrate; extra == "rocrate"
|
|
31
|
-
Requires-Dist: roc-validator; extra == "rocrate"
|
|
31
|
+
Requires-Dist: roc-validator==0.12.2; extra == "rocrate"
|
|
32
32
|
Provides-Extra: all
|
|
33
|
-
Requires-Dist: roc-validator; extra == "all"
|
|
33
|
+
Requires-Dist: roc-validator==0.12.2; extra == "all"
|
|
34
34
|
Requires-Dist: rocrate; extra == "all"
|
|
35
35
|
Dynamic: license-file
|
|
36
36
|
|
|
@@ -96,11 +96,18 @@ It accepts `--provenance_folderpath` (the RO-Crate ZIP), `--benchmark-name`,
|
|
|
96
96
|
`--use-production-rohub` arguments. The software URL and version are read from
|
|
97
97
|
the SoftwareApplication node in the RO-Crate ZIP.
|
|
98
98
|
|
|
99
|
-
`semantic_benchmark.rocrate.create_main_ro(...)`
|
|
100
|
-
aggregate crate
|
|
99
|
+
`semantic_benchmark.rocrate.create_main_ro(...)` always validates the generated
|
|
100
|
+
aggregate crate against `workflow-run-crate-0.5`. The package writes the RO-Crate
|
|
101
101
|
zip, unpacks it to a validation directory, and runs `validate_rocrate(...)`.
|
|
102
102
|
Aggregate creation requires `subcrate_paths`, the exact reporter RO-Crate ZIPs
|
|
103
|
-
from completed runs
|
|
103
|
+
from completed runs, and `workflow_path`, a YAML file used as the main workflow.
|
|
104
|
+
The CLI accepts `--workflow-path` and one `--subcrate-path` per run. Each subcrate
|
|
105
|
+
is the result of a `CreateAction` whose instrument is the YAML workflow; matched
|
|
106
|
+
configuration values are action inputs and extracted metrics are action results.
|
|
107
|
+
Pass `agent_name` and `agent_orcid` from the reporter configuration's
|
|
108
|
+
`report-rocrate-agent-name` and `report-rocrate-agent-orcid` values. They identify
|
|
109
|
+
the workflow author and creator in the aggregate crate. The CLI accepts
|
|
110
|
+
`--agent-name` and `--agent-orcid`.
|
|
104
111
|
|
|
105
112
|
Repository-specific projects can override the packaged RoHub defaults with:
|
|
106
113
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rocrate/__init__.py
RENAMED
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rocrate/validation.py
RENAMED
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/__init__.py
RENAMED
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/download.py
RENAMED
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/rohub_config.json
RENAMED
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/rohub/upload.py
RENAMED
|
File without changes
|
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/__init__.py
RENAMED
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/loader.py
RENAMED
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark/semantics/vocabulary.py
RENAMED
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{semantic_benchmark-0.4.2 → semantic_benchmark-0.4.4}/src/semantic_benchmark.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|